From 6526fa0e237601c7b818b1178dad61b9b3d743b1 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 21 Jun 2011 03:05:17 +0000 Subject: Mark the card as bad on shutdown. This means that bus_child_present will return false on shutdown and massive spewage from usb disappears for usb cardbus adapters. --- sys/dev/pccbb/pccbb_pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/dev/pccbb/pccbb_pci.c b/sys/dev/pccbb/pccbb_pci.c index c89e5ad..6cdc4e4 100644 --- a/sys/dev/pccbb/pccbb_pci.c +++ b/sys/dev/pccbb/pccbb_pci.c @@ -658,6 +658,12 @@ cbb_pci_shutdown(device_t brdev) struct cbb_softc *sc = (struct cbb_softc *)device_get_softc(brdev); /* + * We're about to pull the rug out from the card, so mark it as + * gone to prevent harm. + */ + sc->cardok = 0; + + /* * Place the cards in reset, turn off the interrupts and power * down the socket. */ -- cgit v1.1 From e42b865a6d703440347be5d80a4d97f4ec740c20 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 21 Jun 2011 03:07:59 +0000 Subject: When we see an interrupt status of 0xffffffff, check to see if the child is still present. If not, return 'handled' and don't print anything (this is expected behavior). We expect an interrupt on eject, power-down and/or shutdown. --- sys/dev/firewire/fwohci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c index cccbc8c..4b147b2 100644 --- a/sys/dev/firewire/fwohci.c +++ b/sys/dev/firewire/fwohci.c @@ -2072,8 +2072,9 @@ fwohci_check_stat(struct fwohci_softc *sc) FW_GLOCK_ASSERT(&sc->fc); stat = OREAD(sc, FWOHCI_INTSTAT); if (stat == 0xffffffff) { - device_printf(sc->fc.dev, - "device physically ejected?\n"); + if (!bus_child_present(sc->fc.dev)) + return (FILTER_HANDLED); + device_printf(sc->fc.dev, "device physically ejected?\n"); return (FILTER_STRAY); } if (stat) -- cgit v1.1 From 8e166a461cb07c7f1e283eaeb4013edcaaccad09 Mon Sep 17 00:00:00 2001 From: ae Date: Tue, 21 Jun 2011 04:06:39 +0000 Subject: The "size" param needs no adjusting to stripeoffset. Reported by: Kris Moore --- sbin/geom/class/part/geom_part.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c index eaf5845..a6840e2 100644 --- a/sbin/geom/class/part/geom_part.c +++ b/sbin/geom/class/part/geom_part.c @@ -499,8 +499,8 @@ gpart_autofill(struct gctl_req *req) /* Adjust parameters to stripeoffset */ offset = pp->lg_stripeoffset / pp->lg_sectorsize; start = ALIGNUP(start + offset, alignment); - if (size + offset > alignment) - size = ALIGNDOWN(size + offset, alignment); + if (size > alignment) + size = ALIGNDOWN(size, alignment); first = (off_t)strtoimax(find_geomcfg(gp, "first"), NULL, 0); last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0); -- cgit v1.1 From d740ec2e3548be76883ec841b23261317085d6ba Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 21 Jun 2011 04:46:00 +0000 Subject: Mod the offset padding by alignment. Without this change we may pad too much when underlying GEOM object have a zero stripesize. MFC after: 1 month --- sbin/geom/class/part/geom_part.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c index a6840e2..389c274 100644 --- a/sbin/geom/class/part/geom_part.c +++ b/sbin/geom/class/part/geom_part.c @@ -362,7 +362,7 @@ gpart_autofill_resize(struct gctl_req *req) goto done; } - offset = pp->lg_stripeoffset / pp->lg_sectorsize; + offset = (pp->lg_stripeoffset / pp->lg_sectorsize) % alignment; last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0); LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { s = find_provcfg(pp, "index"); @@ -497,7 +497,7 @@ gpart_autofill(struct gctl_req *req) alignment = len; /* Adjust parameters to stripeoffset */ - offset = pp->lg_stripeoffset / pp->lg_sectorsize; + offset = (pp->lg_stripeoffset / pp->lg_sectorsize) % alignment; start = ALIGNUP(start + offset, alignment); if (size > alignment) size = ALIGNDOWN(size, alignment); -- cgit v1.1 From 17eca2a95b2419792712d24e63d751d8be06f6a8 Mon Sep 17 00:00:00 2001 From: ae Date: Tue, 21 Jun 2011 06:06:47 +0000 Subject: Do not use SET_HOST_IPLEN() macro for IPv6 packets. PR: kern/157239 MFC after: 2 weeks --- sys/netinet/ipfw/ip_dn_io.c | 1 - sys/netinet/ipfw/ip_fw_pfil.c | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/netinet/ipfw/ip_dn_io.c b/sys/netinet/ipfw/ip_dn_io.c index bcb12ae..6766416 100644 --- a/sys/netinet/ipfw/ip_dn_io.c +++ b/sys/netinet/ipfw/ip_dn_io.c @@ -668,7 +668,6 @@ dummynet_send(struct mbuf *m) break; case DIR_OUT | PROTO_IPV6: - SET_HOST_IPLEN(mtod(m, struct ip *)); ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL); break; #endif diff --git a/sys/netinet/ipfw/ip_fw_pfil.c b/sys/netinet/ipfw/ip_fw_pfil.c index 248e4dd..f076436 100644 --- a/sys/netinet/ipfw/ip_fw_pfil.c +++ b/sys/netinet/ipfw/ip_fw_pfil.c @@ -127,8 +127,9 @@ again: args.rule = *((struct ipfw_rule_ref *)(tag+1)); m_tag_delete(*m0, tag); if (args.rule.info & IPFW_ONEPASS) { - SET_HOST_IPLEN(mtod(*m0, struct ip *)); - return 0; + if (mtod(*m0, struct ip *)->ip_v == 4) + SET_HOST_IPLEN(mtod(*m0, struct ip *)); + return (0); } } -- cgit v1.1 From a8e6967ab3a3ba41bc8f4637e9d5bf715848e8c6 Mon Sep 17 00:00:00 2001 From: bz Date: Tue, 21 Jun 2011 07:19:03 +0000 Subject: Garbage collect never used global, sysctl, externs. MFC after: 1 week --- sys/net/route.c | 6 ------ sys/net/route.h | 2 -- 2 files changed, 8 deletions(-) diff --git a/sys/net/route.c b/sys/net/route.c index a6f910e..9c7dfac 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -116,12 +116,6 @@ VNET_DEFINE(int, rttrash); /* routes not in table but not freed */ static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */ #define V_rtzone VNET(rtzone) -#if 0 -/* default fib for tunnels to use */ -u_int tunnel_fib = 0; -SYSCTL_INT(_net, OID_AUTO, tunnelfib, CTLFLAG_RD, &tunnel_fib, 0, ""); -#endif - /* * handler for net.my_fibnum */ diff --git a/sys/net/route.h b/sys/net/route.h index 5031533..0bc72d7 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -108,8 +108,6 @@ struct rt_metrics { #endif extern u_int rt_numfibs; /* number fo usable routing tables */ -extern u_int tunnel_fib; /* tunnels use these */ -extern u_int fwd_fib; /* packets being forwarded use these routes */ /* * XXX kernel function pointer `rt_output' is visible to applications. */ -- cgit v1.1 From c0d149ddb385e3c106d6ec8199c47cdddb57b5cf Mon Sep 17 00:00:00 2001 From: ae Date: Tue, 21 Jun 2011 10:35:20 +0000 Subject: When user specifies the bootcode with size smaller than VTOC_BOOTCODE, gpart_write_partcode_vtoc8 does access out of range of allocated memory. Check size of bootcode before writing it. Pointed out by: ru MFC after: 1 week --- sbin/geom/class/part/geom_part.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c index 389c274..a456911 100644 --- a/sbin/geom/class/part/geom_part.c +++ b/sbin/geom/class/part/geom_part.c @@ -1208,8 +1208,11 @@ gpart_bootcode(struct gctl_req *req, unsigned int fl) if (idx == 0) errx(EXIT_FAILURE, "missing -i option"); gpart_write_partcode(gp, idx, partcode, partsize); - } else + } else { + if (partsize != VTOC_BOOTSIZE) + errx(EXIT_FAILURE, "invalid bootcode"); gpart_write_partcode_vtoc8(gp, idx, partcode); + } } else if (bootcode == NULL) errx(EXIT_FAILURE, "no -b nor -p"); -- cgit v1.1 From 17293d73f86fdd3a8fac6facf760f336b9780f6a Mon Sep 17 00:00:00 2001 From: alc Date: Tue, 21 Jun 2011 12:38:40 +0000 Subject: Use a non-standard page size that is supported. --- sys/ia64/conf/NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/ia64/conf/NOTES b/sys/ia64/conf/NOTES index 3f38218..0f8a4e7 100644 --- a/sys/ia64/conf/NOTES +++ b/sys/ia64/conf/NOTES @@ -25,7 +25,7 @@ options LOG2_ID_PAGE_SIZE=27 # 128M # option: LOG2_PAGE_SIZE # Specify the log2 size of the page to be used for virtual memory management. # The page size being equal to 1< Date: Tue, 21 Jun 2011 17:59:51 +0000 Subject: Minor cleanups to ulog-helper: - Remove unneeded linking against libmd. libulog depends on this library, but the ulog-helper tool itself does not. - Change the comment at the top to mention utmpx instead of utmp, wtmp and lastlog. - Simply use user_from_uid() to translate to a username string. - Put variable declarations together. --- libexec/ulog-helper/Makefile | 4 ++-- libexec/ulog-helper/ulog-helper.c | 24 ++++++++++-------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/libexec/ulog-helper/Makefile b/libexec/ulog-helper/Makefile index 3c1770c..c1697c8 100644 --- a/libexec/ulog-helper/Makefile +++ b/libexec/ulog-helper/Makefile @@ -5,7 +5,7 @@ BINOWN= root BINMODE=4555 NO_MAN= -DPADD= ${LIBULOG} ${LIBMD} -LDADD= -lulog -lmd +DPADD= ${LIBULOG} +LDADD= -lulog .include diff --git a/libexec/ulog-helper/ulog-helper.c b/libexec/ulog-helper/ulog-helper.c index eaef778..31b40e9 100644 --- a/libexec/ulog-helper/ulog-helper.c +++ b/libexec/ulog-helper/ulog-helper.c @@ -36,11 +36,11 @@ __FBSDID("$FreeBSD$"); /* * This setuid helper utility writes user login records to disk. - * Unprivileged processes are not capable of writing records to utmp, - * wtmp and lastlog, but we do want to allow this for pseudo-terminals. - * Because a file descriptor to a pseudo-terminal master device can only - * be obtained by processes using the pseudo-terminal, we expect such a - * descriptor on stdin. + * Unprivileged processes are not capable of writing records to utmpx, + * but we do want to allow this for pseudo-terminals. Because a file + * descriptor to a pseudo-terminal master device can only be obtained by + * processes using the pseudo-terminal, we expect such a descriptor on + * stdin. * * It uses the real user ID of the calling process to determine the * username. It does allow users to log arbitrary hostnames. @@ -49,26 +49,22 @@ __FBSDID("$FreeBSD$"); int main(int argc, char *argv[]) { - const char *line; + const char *line, *user, *host; /* Device line name. */ if ((line = ptsname(STDIN_FILENO)) == NULL) return (EX_USAGE); if ((argc == 2 || argc == 3) && strcmp(argv[1], "login") == 0) { - struct passwd *pwd; - const char *host = NULL; - /* Username. */ - pwd = getpwuid(getuid()); - if (pwd == NULL) + user = user_from_uid(getuid(), 1); + if (user == NULL) return (EX_OSERR); /* Hostname. */ - if (argc == 3) - host = argv[2]; + host = argc == 3 ? argv[2] : NULL; - ulog_login(line, pwd->pw_name, host); + ulog_login(line, user, host); return (EX_OK); } else if (argc == 2 && strcmp(argv[1], "logout") == 0) { ulog_logout(line); -- cgit v1.1 From 1614d1809fabb1b79cc0ff5b9430b42b451aaa47 Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 21 Jun 2011 19:15:23 +0000 Subject: Change sparc64 to use the initial exec TLS model, too. This avoids random assertion failures in _malloc_thread_cleanup(). --- lib/libc/stdlib/malloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c index 48d9c14..5290512 100644 --- a/lib/libc/stdlib/malloc.c +++ b/lib/libc/stdlib/malloc.c @@ -234,7 +234,7 @@ __FBSDID("$FreeBSD$"); #ifdef __sparc64__ # define LG_QUANTUM 4 # define LG_SIZEOF_PTR 3 -# define TLS_MODEL /* default */ +# define TLS_MODEL __attribute__((tls_model("initial-exec"))) #endif #ifdef __amd64__ # define LG_QUANTUM 4 -- cgit v1.1 From ddab6d36442cfeeb35ee47cbca11519b0173b9f2 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 21 Jun 2011 19:29:27 +0000 Subject: Use AcpiWalkResources() to parse the resource list from _CRS rather than using a home-rolled loop. While here, add support for 64-bit address range resources. Silence on: acpi@ (older version) --- sys/dev/acpica/acpi_resource.c | 596 +++++++++++++++++++---------------------- sys/dev/acpica/acpivar.h | 22 +- 2 files changed, 282 insertions(+), 336 deletions(-) diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c index c83b679..5c103df 100644 --- a/sys/dev/acpica/acpi_resource.c +++ b/sys/dev/acpica/acpi_resource.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -139,332 +140,277 @@ acpi_config_intr(device_t dev, ACPI_RESOURCE *res) INTR_POLARITY_HIGH : INTR_POLARITY_LOW); } -/* - * Fetch a device's resources and associate them with the device. - * - * Note that it might be nice to also locate ACPI-specific resource items, such - * as GPE bits. - * - * We really need to split the resource-fetching code out from the - * resource-parsing code, since we may want to use the parsing - * code for _PRS someday. - */ -ACPI_STATUS -acpi_parse_resources(device_t dev, ACPI_HANDLE handle, - struct acpi_parse_resource_set *set, void *arg) -{ - ACPI_BUFFER buf; - ACPI_RESOURCE *res; - char *curr, *last; - ACPI_STATUS status; - void *context; +struct acpi_resource_context { + struct acpi_parse_resource_set *set; + device_t dev; + void *context; +}; - ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); +#ifdef ACPI_DEBUG_OUTPUT +static const char * +acpi_address_range_name(UINT8 ResourceType) +{ + static char buf[16]; + + switch (ResourceType) { + case ACPI_MEMORY_RANGE: + return ("Memory"); + case ACPI_IO_RANGE: + return ("IO"); + case ACPI_BUS_NUMBER_RANGE: + return ("Bus Number"); + default: + snprintf(buf, sizeof(buf), "type %u", ResourceType); + return (buf); + } +} +#endif + +static ACPI_STATUS +acpi_parse_resource(ACPI_RESOURCE *res, void *context) +{ + struct acpi_parse_resource_set *set; + struct acpi_resource_context *arc; + UINT64 min, max, length, gran; + const char *name; + device_t dev; - /* - * Special-case some devices that abuse _PRS/_CRS to mean - * something other than "I consume this resource". - * - * XXX do we really need this? It's only relevant once - * we start always-allocating these resources, and even - * then, the only special-cased device is likely to be - * the PCI interrupt link. - */ + arc = context; + dev = arc->dev; + set = arc->set; - /* Fetch the device's current resources. */ - buf.Length = ACPI_ALLOCATE_BUFFER; - if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) { - if (status != AE_NOT_FOUND && status != AE_TYPE) - printf("can't fetch resources for %s - %s\n", - acpi_name(handle), AcpiFormatException(status)); - return_ACPI_STATUS (status); - } - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n", - acpi_name(handle), (long)buf.Length)); - set->set_init(dev, arg, &context); - - /* Iterate through the resources */ - curr = buf.Pointer; - last = (char *)buf.Pointer + buf.Length; - while (curr < last) { - res = (ACPI_RESOURCE *)curr; - curr += res->Length; - - /* Handle the individual resource types */ - switch(res->Type) { - case ACPI_RESOURCE_TYPE_END_TAG: - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n")); - curr = last; + switch (res->Type) { + case ACPI_RESOURCE_TYPE_END_TAG: + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n")); + break; + case ACPI_RESOURCE_TYPE_FIXED_IO: + if (res->Data.FixedIo.AddressLength <= 0) break; - case ACPI_RESOURCE_TYPE_FIXED_IO: - if (res->Data.FixedIo.AddressLength <= 0) - break; - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n", - res->Data.FixedIo.Address, - res->Data.FixedIo.AddressLength)); - set->set_ioport(dev, context, - res->Data.FixedIo.Address, - res->Data.FixedIo.AddressLength); + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n", + res->Data.FixedIo.Address, res->Data.FixedIo.AddressLength)); + set->set_ioport(dev, arc->context, res->Data.FixedIo.Address, + res->Data.FixedIo.AddressLength); + break; + case ACPI_RESOURCE_TYPE_IO: + if (res->Data.Io.AddressLength <= 0) break; - case ACPI_RESOURCE_TYPE_IO: - if (res->Data.Io.AddressLength <= 0) - break; - if (res->Data.Io.Minimum == res->Data.Io.Maximum) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n", - res->Data.Io.Minimum, - res->Data.Io.AddressLength)); - set->set_ioport(dev, context, - res->Data.Io.Minimum, - res->Data.Io.AddressLength); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n", - res->Data.Io.Minimum, - res->Data.Io.Maximum, - res->Data.Io.AddressLength)); - set->set_iorange(dev, context, - res->Data.Io.Minimum, - res->Data.Io.Maximum, - res->Data.Io.AddressLength, - res->Data.Io.Alignment); - } + if (res->Data.Io.Minimum == res->Data.Io.Maximum) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n", + res->Data.Io.Minimum, res->Data.Io.AddressLength)); + set->set_ioport(dev, arc->context, res->Data.Io.Minimum, + res->Data.Io.AddressLength); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n", + res->Data.Io.Minimum, res->Data.Io.Maximum, + res->Data.Io.AddressLength)); + set->set_iorange(dev, arc->context, res->Data.Io.Minimum, + res->Data.Io.Maximum, res->Data.Io.AddressLength, + res->Data.Io.Alignment); + } + break; + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + if (res->Data.FixedMemory32.AddressLength <= 0) break; - case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: - if (res->Data.FixedMemory32.AddressLength <= 0) - break; - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n", - res->Data.FixedMemory32.Address, - res->Data.FixedMemory32.AddressLength)); - set->set_memory(dev, context, - res->Data.FixedMemory32.Address, - res->Data.FixedMemory32.AddressLength); + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n", + res->Data.FixedMemory32.Address, + res->Data.FixedMemory32.AddressLength)); + set->set_memory(dev, arc->context, res->Data.FixedMemory32.Address, + res->Data.FixedMemory32.AddressLength); + break; + case ACPI_RESOURCE_TYPE_MEMORY32: + if (res->Data.Memory32.AddressLength <= 0) break; - case ACPI_RESOURCE_TYPE_MEMORY32: - if (res->Data.Memory32.AddressLength <= 0) - break; - if (res->Data.Memory32.Minimum == - res->Data.Memory32.Maximum) { - - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n", - res->Data.Memory32.Minimum, - res->Data.Memory32.AddressLength)); - set->set_memory(dev, context, - res->Data.Memory32.Minimum, - res->Data.Memory32.AddressLength); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n", - res->Data.Memory32.Minimum, - res->Data.Memory32.Maximum, - res->Data.Memory32.AddressLength)); - set->set_memoryrange(dev, context, - res->Data.Memory32.Minimum, - res->Data.Memory32.Maximum, - res->Data.Memory32.AddressLength, - res->Data.Memory32.Alignment); - } + if (res->Data.Memory32.Minimum == res->Data.Memory32.Maximum) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n", + res->Data.Memory32.Minimum, res->Data.Memory32.AddressLength)); + set->set_memory(dev, arc->context, res->Data.Memory32.Minimum, + res->Data.Memory32.AddressLength); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n", + res->Data.Memory32.Minimum, res->Data.Memory32.Maximum, + res->Data.Memory32.AddressLength)); + set->set_memoryrange(dev, arc->context, res->Data.Memory32.Minimum, + res->Data.Memory32.Maximum, res->Data.Memory32.AddressLength, + res->Data.Memory32.Alignment); + } + break; + case ACPI_RESOURCE_TYPE_MEMORY24: + if (res->Data.Memory24.AddressLength <= 0) break; - case ACPI_RESOURCE_TYPE_MEMORY24: - if (res->Data.Memory24.AddressLength <= 0) - break; - if (res->Data.Memory24.Minimum == - res->Data.Memory24.Maximum) { - - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n", - res->Data.Memory24.Minimum, - res->Data.Memory24.AddressLength)); - set->set_memory(dev, context, res->Data.Memory24.Minimum, - res->Data.Memory24.AddressLength); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n", - res->Data.Memory24.Minimum, - res->Data.Memory24.Maximum, - res->Data.Memory24.AddressLength)); - set->set_memoryrange(dev, context, - res->Data.Memory24.Minimum, - res->Data.Memory24.Maximum, - res->Data.Memory24.AddressLength, - res->Data.Memory24.Alignment); - } + if (res->Data.Memory24.Minimum == res->Data.Memory24.Maximum) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n", + res->Data.Memory24.Minimum, res->Data.Memory24.AddressLength)); + set->set_memory(dev, arc->context, res->Data.Memory24.Minimum, + res->Data.Memory24.AddressLength); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n", + res->Data.Memory24.Minimum, res->Data.Memory24.Maximum, + res->Data.Memory24.AddressLength)); + set->set_memoryrange(dev, arc->context, res->Data.Memory24.Minimum, + res->Data.Memory24.Maximum, res->Data.Memory24.AddressLength, + res->Data.Memory24.Alignment); + } + break; + case ACPI_RESOURCE_TYPE_IRQ: + /* + * from 1.0b 6.4.2 + * "This structure is repeated for each separate interrupt + * required" + */ + set->set_irq(dev, arc->context, res->Data.Irq.Interrupts, + res->Data.Irq.InterruptCount, res->Data.Irq.Triggering, + res->Data.Irq.Polarity); + break; + case ACPI_RESOURCE_TYPE_DMA: + /* + * from 1.0b 6.4.3 + * "This structure is repeated for each separate DMA channel + * required" + */ + set->set_drq(dev, arc->context, res->Data.Dma.Channels, + res->Data.Dma.ChannelCount); + break; + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n")); + set->set_start_dependent(dev, arc->context, + res->Data.StartDpf.CompatibilityPriority); + break; + case ACPI_RESOURCE_TYPE_END_DEPENDENT: + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n")); + set->set_end_dependent(dev, arc->context); + break; + case ACPI_RESOURCE_TYPE_ADDRESS16: + case ACPI_RESOURCE_TYPE_ADDRESS32: + case ACPI_RESOURCE_TYPE_ADDRESS64: + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + switch (res->Type) { + case ACPI_RESOURCE_TYPE_ADDRESS16: + gran = res->Data.Address16.Granularity; + min = res->Data.Address16.Minimum; + max = res->Data.Address16.Maximum; + length = res->Data.Address16.AddressLength; + name = "Address16"; + break; + case ACPI_RESOURCE_TYPE_ADDRESS32: + gran = res->Data.Address32.Granularity; + min = res->Data.Address32.Minimum; + max = res->Data.Address32.Maximum; + length = res->Data.Address32.AddressLength; + name = "Address32"; + break; + case ACPI_RESOURCE_TYPE_ADDRESS64: + gran = res->Data.Address64.Granularity; + min = res->Data.Address64.Minimum; + max = res->Data.Address64.Maximum; + length = res->Data.Address64.AddressLength; + name = "Address64"; break; - case ACPI_RESOURCE_TYPE_IRQ: - /* - * from 1.0b 6.4.2 - * "This structure is repeated for each separate interrupt - * required" - */ - set->set_irq(dev, context, res->Data.Irq.Interrupts, - res->Data.Irq.InterruptCount, res->Data.Irq.Triggering, - res->Data.Irq.Polarity); + default: + KASSERT(res->Type == ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64, + ("should never happen")); + gran = res->Data.ExtAddress64.Granularity; + min = res->Data.ExtAddress64.Minimum; + max = res->Data.ExtAddress64.Maximum; + length = res->Data.ExtAddress64.AddressLength; + name = "ExtAddress64"; break; - case ACPI_RESOURCE_TYPE_DMA: - /* - * from 1.0b 6.4.3 - * "This structure is repeated for each separate dma channel - * required" - */ - set->set_drq(dev, context, res->Data.Dma.Channels, - res->Data.Dma.ChannelCount); + } + if (length <= 0) break; - case ACPI_RESOURCE_TYPE_START_DEPENDENT: - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n")); - set->set_start_dependent(dev, context, - res->Data.StartDpf.CompatibilityPriority); + if (res->Data.Address.ProducerConsumer != ACPI_CONSUMER) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "ignored %s %s producer\n", name, + acpi_address_range_name(res->Data.Address.ResourceType))); break; - case ACPI_RESOURCE_TYPE_END_DEPENDENT: - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n")); - set->set_end_dependent(dev, context); + } + if (res->Data.Address.ResourceType != ACPI_MEMORY_RANGE && + res->Data.Address.ResourceType != ACPI_IO_RANGE) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "ignored %s for non-memory, non-I/O\n", name)); break; - case ACPI_RESOURCE_TYPE_ADDRESS32: - if (res->Data.Address32.AddressLength <= 0) - break; - if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "ignored Address32 %s producer\n", - res->Data.Address32.ResourceType == ACPI_IO_RANGE ? - "IO" : "Memory")); - break; - } - if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE && - res->Data.Address32.ResourceType != ACPI_IO_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "ignored Address32 for non-memory, non-I/O\n")); - break; - } + } - if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED && - res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) { - - if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address32/Memory 0x%x/%d\n", - res->Data.Address32.Minimum, - res->Data.Address32.AddressLength)); - set->set_memory(dev, context, - res->Data.Address32.Minimum, - res->Data.Address32.AddressLength); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address32/IO 0x%x/%d\n", - res->Data.Address32.Minimum, - res->Data.Address32.AddressLength)); - set->set_ioport(dev, context, - res->Data.Address32.Minimum, - res->Data.Address32.AddressLength); - } - } else { - if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address32/Memory 0x%x-0x%x/%d\n", - res->Data.Address32.Minimum, - res->Data.Address32.Maximum, - res->Data.Address32.AddressLength)); - set->set_memoryrange(dev, context, - res->Data.Address32.Minimum, - res->Data.Address32.Maximum, - res->Data.Address32.AddressLength, - res->Data.Address32.Granularity); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address32/IO 0x%x-0x%x/%d\n", - res->Data.Address32.Minimum, - res->Data.Address32.Maximum, - res->Data.Address32.AddressLength)); - set->set_iorange(dev, context, - res->Data.Address32.Minimum, - res->Data.Address32.Maximum, - res->Data.Address32.AddressLength, - res->Data.Address32.Granularity); - } - } +#ifdef __i386__ + if (min > ULONG_MAX || (res->Data.Address.MaxAddressFixed && max > + ULONG_MAX)) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored %s above 4G\n", + name)); break; - case ACPI_RESOURCE_TYPE_ADDRESS16: - if (res->Data.Address16.AddressLength <= 0) - break; - if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "ignored Address16 %s producer\n", - res->Data.Address16.ResourceType == ACPI_IO_RANGE ? - "IO" : "Memory")); - break; - } - if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE && - res->Data.Address16.ResourceType != ACPI_IO_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "ignored Address16 for non-memory, non-I/O\n")); - break; + } + if (max > ULONG_MAX) + max = ULONG_MAX; +#endif + if (res->Data.Address.MinAddressFixed == ACPI_ADDRESS_FIXED && + res->Data.Address.MaxAddressFixed == ACPI_ADDRESS_FIXED) { + if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%x/%d\n", + name, min, length)); + set->set_memory(dev, arc->context, min, length); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%x/%d\n", name, + min, length)); + set->set_ioport(dev, arc->context, min, length); } - - if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED && - res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) { - - if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address16/Memory 0x%x/%d\n", - res->Data.Address16.Minimum, - res->Data.Address16.AddressLength)); - set->set_memory(dev, context, - res->Data.Address16.Minimum, - res->Data.Address16.AddressLength); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address16/IO 0x%x/%d\n", - res->Data.Address16.Minimum, - res->Data.Address16.AddressLength)); - set->set_ioport(dev, context, - res->Data.Address16.Minimum, - res->Data.Address16.AddressLength); - } + } else { + if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%x-0x%x/%d\n", + name, min, max, length)); + set->set_memoryrange(dev, arc->context, min, max, length, gran); } else { - if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address16/Memory 0x%x-0x%x/%d\n", - res->Data.Address16.Minimum, - res->Data.Address16.Maximum, - res->Data.Address16.AddressLength)); - set->set_memoryrange(dev, context, - res->Data.Address16.Minimum, - res->Data.Address16.Maximum, - res->Data.Address16.AddressLength, - res->Data.Address16.Granularity); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "Address16/IO 0x%x-0x%x/%d\n", - res->Data.Address16.Minimum, - res->Data.Address16.Maximum, - res->Data.Address16.AddressLength)); - set->set_iorange(dev, context, - res->Data.Address16.Minimum, - res->Data.Address16.Maximum, - res->Data.Address16.AddressLength, - res->Data.Address16.Granularity); - } - } - break; - case ACPI_RESOURCE_TYPE_ADDRESS64: - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "unimplemented Address64 resource\n")); - break; - case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "ignored ExtIRQ producer\n")); - break; + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%x-0x%x/%d\n", + name, min, max, length)); + set->set_iorange(dev, arc->context, min, max, length, gran); } - set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts, - res->Data.ExtendedIrq.InterruptCount, - res->Data.ExtendedIrq.Triggering, - res->Data.ExtendedIrq.Polarity); - break; - case ACPI_RESOURCE_TYPE_VENDOR: - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, - "unimplemented VendorSpecific resource\n")); - break; - default: + } + break; + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) { + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "ignored ExtIRQ producer\n")); break; } - } + set->set_ext_irq(dev, arc->context, res->Data.ExtendedIrq.Interrupts, + res->Data.ExtendedIrq.InterruptCount, + res->Data.ExtendedIrq.Triggering, res->Data.ExtendedIrq.Polarity); + break; + case ACPI_RESOURCE_TYPE_VENDOR: + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "unimplemented VendorSpecific resource\n")); + break; + default: + break; + } + return (AE_OK); +} - AcpiOsFree(buf.Pointer); - set->set_done(dev, context); +/* + * Fetch a device's resources and associate them with the device. + * + * Note that it might be nice to also locate ACPI-specific resource items, such + * as GPE bits. + * + * We really need to split the resource-fetching code out from the + * resource-parsing code, since we may want to use the parsing + * code for _PRS someday. + */ +ACPI_STATUS +acpi_parse_resources(device_t dev, ACPI_HANDLE handle, + struct acpi_parse_resource_set *set, void *arg) +{ + struct acpi_resource_context arc; + ACPI_STATUS status; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + set->set_init(dev, arg, &arc.context); + arc.set = set; + arc.dev = dev; + status = AcpiWalkResources(handle, "_CRS", acpi_parse_resource, &arc); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + printf("can't fetch resources for %s - %s\n", + acpi_name(handle), AcpiFormatException(status)); + return_ACPI_STATUS (status); + } + set->set_done(dev, arc.context); return_ACPI_STATUS (AE_OK); } @@ -475,20 +421,20 @@ acpi_parse_resources(device_t dev, ACPI_HANDLE handle, static void acpi_res_set_init(device_t dev, void *arg, void **context); static void acpi_res_set_done(device_t dev, void *context); static void acpi_res_set_ioport(device_t dev, void *context, - u_int32_t base, u_int32_t length); + uint64_t base, uint64_t length); static void acpi_res_set_iorange(device_t dev, void *context, - u_int32_t low, u_int32_t high, - u_int32_t length, u_int32_t align); + uint64_t low, uint64_t high, + uint64_t length, uint64_t align); static void acpi_res_set_memory(device_t dev, void *context, - u_int32_t base, u_int32_t length); + uint64_t base, uint64_t length); static void acpi_res_set_memoryrange(device_t dev, void *context, - u_int32_t low, u_int32_t high, - u_int32_t length, u_int32_t align); -static void acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, + uint64_t low, uint64_t high, + uint64_t length, uint64_t align); +static void acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count, int trig, int pol); static void acpi_res_set_ext_irq(device_t dev, void *context, - u_int32_t *irq, int count, int trig, int pol); -static void acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, + uint32_t *irq, int count, int trig, int pol); +static void acpi_res_set_drq(device_t dev, void *context, uint8_t *drq, int count); static void acpi_res_set_start_dependent(device_t dev, void *context, int preference); @@ -539,8 +485,8 @@ acpi_res_set_done(device_t dev, void *context) } static void -acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, - u_int32_t length) +acpi_res_set_ioport(device_t dev, void *context, uint64_t base, + uint64_t length) { struct acpi_res_context *cp = (struct acpi_res_context *)context; @@ -550,8 +496,8 @@ acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, } static void -acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, - u_int32_t high, u_int32_t length, u_int32_t align) +acpi_res_set_iorange(device_t dev, void *context, uint64_t low, + uint64_t high, uint64_t length, uint64_t align) { struct acpi_res_context *cp = (struct acpi_res_context *)context; @@ -561,8 +507,8 @@ acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, } static void -acpi_res_set_memory(device_t dev, void *context, u_int32_t base, - u_int32_t length) +acpi_res_set_memory(device_t dev, void *context, uint64_t base, + uint64_t length) { struct acpi_res_context *cp = (struct acpi_res_context *)context; @@ -573,8 +519,8 @@ acpi_res_set_memory(device_t dev, void *context, u_int32_t base, } static void -acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, - u_int32_t high, u_int32_t length, u_int32_t align) +acpi_res_set_memoryrange(device_t dev, void *context, uint64_t low, + uint64_t high, uint64_t length, uint64_t align) { struct acpi_res_context *cp = (struct acpi_res_context *)context; @@ -584,7 +530,7 @@ acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, } static void -acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count, +acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count, int trig, int pol) { struct acpi_res_context *cp = (struct acpi_res_context *)context; @@ -600,7 +546,7 @@ acpi_res_set_irq(device_t dev, void *context, u_int8_t *irq, int count, } static void -acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count, +acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count, int trig, int pol) { struct acpi_res_context *cp = (struct acpi_res_context *)context; @@ -616,7 +562,7 @@ acpi_res_set_ext_irq(device_t dev, void *context, u_int32_t *irq, int count, } static void -acpi_res_set_drq(device_t dev, void *context, u_int8_t *drq, int count) +acpi_res_set_drq(device_t dev, void *context, uint8_t *drq, int count) { struct acpi_res_context *cp = (struct acpi_res_context *)context; diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index a74cd75..8735776 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -355,19 +355,19 @@ BOOLEAN acpi_MatchHid(ACPI_HANDLE h, const char *hid); struct acpi_parse_resource_set { void (*set_init)(device_t dev, void *arg, void **context); void (*set_done)(device_t dev, void *context); - void (*set_ioport)(device_t dev, void *context, uint32_t base, - uint32_t length); - void (*set_iorange)(device_t dev, void *context, uint32_t low, - uint32_t high, uint32_t length, uint32_t align); - void (*set_memory)(device_t dev, void *context, uint32_t base, - uint32_t length); - void (*set_memoryrange)(device_t dev, void *context, uint32_t low, - uint32_t high, uint32_t length, uint32_t align); - void (*set_irq)(device_t dev, void *context, u_int8_t *irq, + void (*set_ioport)(device_t dev, void *context, uint64_t base, + uint64_t length); + void (*set_iorange)(device_t dev, void *context, uint64_t low, + uint64_t high, uint64_t length, uint64_t align); + void (*set_memory)(device_t dev, void *context, uint64_t base, + uint64_t length); + void (*set_memoryrange)(device_t dev, void *context, uint64_t low, + uint64_t high, uint64_t length, uint64_t align); + void (*set_irq)(device_t dev, void *context, uint8_t *irq, int count, int trig, int pol); - void (*set_ext_irq)(device_t dev, void *context, u_int32_t *irq, + void (*set_ext_irq)(device_t dev, void *context, uint32_t *irq, int count, int trig, int pol); - void (*set_drq)(device_t dev, void *context, u_int8_t *drq, + void (*set_drq)(device_t dev, void *context, uint8_t *drq, int count); void (*set_start_dependent)(device_t dev, void *context, int preference); -- cgit v1.1 From 51b09ade326c5836f72fe82051d343af43fb78c7 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 21 Jun 2011 19:31:31 +0000 Subject: Minor whitespace and style fixes. --- sys/dev/pci/pci.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 9cd5a1c..b346dd3 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -297,7 +297,7 @@ static int pci_usb_takeover = 1; static int pci_usb_takeover = 0; #endif TUNABLE_INT("hw.pci.usb_early_takeover", &pci_usb_takeover); -SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RD | CTLFLAG_TUN, +SYSCTL_INT(_hw_pci, OID_AUTO, usb_early_takeover, CTLFLAG_RDTUN, &pci_usb_takeover, 1, "Enable early takeover of USB controllers.\n\ Disable this if you depend on BIOS emulation of USB devices, that is\n\ you use USB devices (like keyboard or mouse) but do not load USB drivers"); @@ -2482,7 +2482,8 @@ pci_write_bar(device_t dev, struct pci_map *pm, pci_addr_t base) pci_write_config(dev, pm->pm_reg + 4, base >> 32, 4); pm->pm_value = pci_read_config(dev, pm->pm_reg, 4); if (ln2range == 64) - pm->pm_value |= (pci_addr_t)pci_read_config(dev, pm->pm_reg + 4, 4) << 32; + pm->pm_value |= (pci_addr_t)pci_read_config(dev, + pm->pm_reg + 4, 4) << 32; } struct pci_map * @@ -2680,7 +2681,7 @@ pci_add_map(device_t bus, device_t dev, int reg, struct resource_list *rl, count = (pci_addr_t)1 << mapsize; if (basezero || base == pci_mapbase(testval)) { start = 0; /* Let the parent decide. */ - end = ~0ULL; + end = ~0ul; } else { start = base; end = base + count - 1; -- cgit v1.1 From 2df9331d12f7b78278e2828898debc4238212f5c Mon Sep 17 00:00:00 2001 From: ru Date: Tue, 21 Jun 2011 19:34:57 +0000 Subject: Make ``realpath'' behave like ``realpath .''. --- bin/realpath/realpath.1 | 10 +++++++--- bin/realpath/realpath.c | 16 ++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/bin/realpath/realpath.1 b/bin/realpath/realpath.1 index cf904ed..8df1047 100644 --- a/bin/realpath/realpath.1 +++ b/bin/realpath/realpath.1 @@ -33,7 +33,7 @@ .\" From: src/bin/pwd/pwd.1,v 1.11 2000/11/20 11:39:39 ru Exp .\" $FreeBSD$ .\" -.Dd November 24, 2000 +.Dd June 21, 2011 .Dt REALPATH 1 .Os .Sh NAME @@ -42,8 +42,7 @@ .Sh SYNOPSIS .Nm .Op Fl q -.Ar path -.Op Ar ... +.Op Ar path ... .Sh DESCRIPTION The .Nm @@ -57,6 +56,11 @@ and .Pa /../ in .Ar path . +If +.Ar path +is absent, the current working directory +.Pq Sq Pa .\& +is assumed. .Pp If .Fl q diff --git a/bin/realpath/realpath.c b/bin/realpath/realpath.c index 99f5a9d5..a2ae06b 100644 --- a/bin/realpath/realpath.c +++ b/bin/realpath/realpath.c @@ -44,7 +44,8 @@ main(int argc, char *argv[]) { char buf[PATH_MAX]; char *p; - int ch, i, qflag, rval; + const char *path; + int ch, qflag, rval; qflag = 0; while ((ch = getopt(argc, argv, "q")) != -1) { @@ -59,17 +60,16 @@ main(int argc, char *argv[]) } argc -= optind; argv += optind; - if (argc < 1) - usage(); + path = *argv != NULL ? *argv++ : "."; rval = 0; - for (i = 0; i < argc; i++) { - if ((p = realpath(argv[i], buf)) == NULL) { + do { + if ((p = realpath(path, buf)) == NULL) { if (!qflag) - warn("%s", argv[i]); + warn("%s", path); rval = 1; } else (void)printf("%s\n", p); - } + } while ((path = *argv++) != NULL); exit(rval); } @@ -77,6 +77,6 @@ static void usage(void) { - (void)fprintf(stderr, "usage: realpath [-q] path [...]\n"); + (void)fprintf(stderr, "usage: realpath [-q] [path ...]\n"); exit(1); } -- cgit v1.1 From af32f8cb559748adc106e1e2e118109231eb6954 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Tue, 21 Jun 2011 19:58:29 +0000 Subject: Fix the new NFSv4 server so that it checks for VREAD_ACL when a client does a Getattr for an ACL and not VREAD_ATTRIBUTES. This was found during the recent NFSv4 interoperability Bakeathon. MFC after: 2 weeks --- sys/fs/nfsserver/nfs_nfsdserv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index fc296c0..64aafb4 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -172,11 +172,12 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, fhandle_t fh; int at_root = 0, error = 0, supports_nfsv4acls; struct nfsreferral *refp; - nfsattrbit_t attrbits; + nfsattrbit_t attrbits, tmpbits; struct mount *mp; struct vnode *tvp = NULL; struct vattr va; uint64_t mounted_on_fileno = 0; + accmode_t accmode; if (nd->nd_repstat) return (0); @@ -197,11 +198,20 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram, vput(vp); return (0); } - if (!nd->nd_repstat) - nd->nd_repstat = nfsvno_accchk(vp, - VREAD_ATTRIBUTES, - nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, - NFSACCCHK_VPISLOCKED, NULL); + if (nd->nd_repstat == 0) { + accmode = 0; + NFSSET_ATTRBIT(&tmpbits, &attrbits); + if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_ACL)) { + NFSCLRBIT_ATTRBIT(&tmpbits, NFSATTRBIT_ACL); + accmode |= VREAD_ACL; + } + if (NFSNONZERO_ATTRBIT(&tmpbits)) + accmode |= VREAD_ATTRIBUTES; + if (accmode != 0) + nd->nd_repstat = nfsvno_accchk(vp, accmode, + nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE, + NFSACCCHK_VPISLOCKED, NULL); + } } if (!nd->nd_repstat) nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1); -- cgit v1.1 From 73a54b65fe42e9fc33d5bececcc0586f92ce2351 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 21 Jun 2011 20:33:55 +0000 Subject: Staticify cleanup() which is not referenced in other places. MFC after: 2 weeks --- usr.bin/finger/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/finger/net.c b/usr.bin/finger/net.c index ca98674..2b18b0f 100644 --- a/usr.bin/finger/net.c +++ b/usr.bin/finger/net.c @@ -226,7 +226,7 @@ trying(const struct addrinfo *ai) printf("Trying %s...\n", buf); } -void +static void cleanup(int sig __unused) { #define ERRSTR "Timed out.\n" -- cgit v1.1 From 7ced5ae9ca81d000580d384b7a02def207b32004 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 21 Jun 2011 20:36:10 +0000 Subject: Remove unneeded headers. MFC after: 2 weeks --- usr.bin/lastcomm/lastcomm.c | 2 -- usr.bin/lastcomm/readrec.c | 4 ---- 2 files changed, 6 deletions(-) diff --git a/usr.bin/lastcomm/lastcomm.c b/usr.bin/lastcomm/lastcomm.c index 8852081..e140c70 100644 --- a/usr.bin/lastcomm/lastcomm.c +++ b/usr.bin/lastcomm/lastcomm.c @@ -48,8 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include #include #include diff --git a/usr.bin/lastcomm/readrec.c b/usr.bin/lastcomm/readrec.c index 4883b2a..5de7c5c 100644 --- a/usr.bin/lastcomm/readrec.c +++ b/usr.bin/lastcomm/readrec.c @@ -33,13 +33,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include -#include #include #include -#include #include int readrec_forward(FILE *f, struct acctv2 *av2); -- cgit v1.1 From 3eae89419641f05c8322f7d392d24d7e97e7af77 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 21 Jun 2011 20:44:06 +0000 Subject: Eliminate unneeded headers. --- usr.bin/cmp/regular.c | 2 -- usr.bin/cmp/special.c | 1 - 2 files changed, 3 deletions(-) diff --git a/usr.bin/cmp/regular.c b/usr.bin/cmp/regular.c index e88b2c0..7ed83c1 100644 --- a/usr.bin/cmp/regular.c +++ b/usr.bin/cmp/regular.c @@ -41,12 +41,10 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include #include -#include #include #include "extern.h" diff --git a/usr.bin/cmp/special.c b/usr.bin/cmp/special.c index 08fc887..8225185 100644 --- a/usr.bin/cmp/special.c +++ b/usr.bin/cmp/special.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include "extern.h" -- cgit v1.1 From cee084b03f7ae8330633fa6bdac66995e9d3c1ca Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 21 Jun 2011 20:47:03 +0000 Subject: On machines where we don't need to lock the kernel TSB into the dTLB and thus may basically use the entire 64-bit kernel address space increase the kernel virtual memory to not be limited by VM_KMEM_SIZE_MAX. --- sys/sparc64/sparc64/pmap.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index 876dce3..f917af9 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -384,11 +384,12 @@ pmap_bootstrap(u_int cpu_impl) * public documentation is available for these, the latter just might * not support it, yet. */ - virtsz = roundup(physsz, PAGE_SIZE_4M << (PAGE_SHIFT - TTE_SHIFT)); if (cpu_impl == CPU_IMPL_SPARC64V || - cpu_impl >= CPU_IMPL_ULTRASPARCIIIp) + cpu_impl >= CPU_IMPL_ULTRASPARCIIIp) { tsb_kernel_ldd_phys = 1; - else { + virtsz = roundup(5 / 3 * physsz, PAGE_SIZE_4M << + (PAGE_SHIFT - TTE_SHIFT)); + } else { dtlb_slots_avail = 0; for (i = 0; i < dtlb_slots; i++) { data = dtlb_get_data(i); @@ -401,6 +402,8 @@ pmap_bootstrap(u_int cpu_impl) if (cpu_impl >= CPU_IMPL_ULTRASPARCI && cpu_impl < CPU_IMPL_ULTRASPARCIII) dtlb_slots_avail /= 2; + virtsz = roundup(physsz, PAGE_SIZE_4M << + (PAGE_SHIFT - TTE_SHIFT)); virtsz = MIN(virtsz, (dtlb_slots_avail * PAGE_SIZE_4M) << (PAGE_SHIFT - TTE_SHIFT)); } -- cgit v1.1 From 3cb5b0723fb083aac66b0e60e0b09a7a1439db3f Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 21 Jun 2011 20:48:14 +0000 Subject: On machines where we don't need to lock the kernel TSB into the dTLB and thus may basically use the entire 64-bit kernel address space reduce VM_KMEM_SIZE_SCALE to 1 allowing kernel to use more memory. --- sys/sparc64/include/tsb.h | 1 - sys/sparc64/include/vmparam.h | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/sparc64/include/tsb.h b/sys/sparc64/include/tsb.h index 5fa1190..1fd1e8f 100644 --- a/sys/sparc64/include/tsb.h +++ b/sys/sparc64/include/tsb.h @@ -50,7 +50,6 @@ extern struct tte *tsb_kernel; extern vm_size_t tsb_kernel_mask; extern vm_size_t tsb_kernel_size; extern vm_paddr_t tsb_kernel_phys; -extern u_int tsb_kernel_ldd_phys; static __inline struct tte * tsb_vpntobucket(pmap_t pm, vm_offset_t vpn) diff --git a/sys/sparc64/include/vmparam.h b/sys/sparc64/include/vmparam.h index 1b9e537..6c17b4c 100644 --- a/sys/sparc64/include/vmparam.h +++ b/sys/sparc64/include/vmparam.h @@ -218,7 +218,7 @@ * is the total KVA space allocated for kmem_map. */ #ifndef VM_KMEM_SIZE_SCALE -#define VM_KMEM_SIZE_SCALE (3) +#define VM_KMEM_SIZE_SCALE (tsb_kernel_ldd_phys == 0 ? 3 : 1) #endif /* @@ -238,6 +238,7 @@ #define UMA_MD_SMALL_ALLOC +extern u_int tsb_kernel_ldd_phys; extern vm_offset_t vm_max_kernel_address; /* -- cgit v1.1 From 4f07c4e7c9461b6a6a49882cf69513cadc9dd7c1 Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 21 Jun 2011 20:50:55 +0000 Subject: Fix whitespace --- sys/sparc64/include/vmparam.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/sparc64/include/vmparam.h b/sys/sparc64/include/vmparam.h index 6c17b4c..a0d5ac4 100644 --- a/sys/sparc64/include/vmparam.h +++ b/sys/sparc64/include/vmparam.h @@ -70,7 +70,7 @@ * The number of PHYSSEG entries must be one greater than the number * of phys_avail entries because the phys_avail entry that spans the * largest physical address that is accessible by ISA DMA is split - * into two PHYSSEG entries. + * into two PHYSSEG entries. */ #define VM_PHYSSEG_MAX 64 @@ -136,13 +136,13 @@ * 43 bits of user address space is considered to be "enough", so we ignore it. * * Upper region: 0xffffffffffffffff - * 0xfffff80000000000 - * + * 0xfffff80000000000 + * * Hole: 0xfffff7ffffffffff - * 0x0000080000000000 + * 0x0000080000000000 * * Lower region: 0x000007ffffffffff - * 0x0000000000000000 + * 0x0000000000000000 * * In general we ignore the upper region, and use the lower region as mappable * space. -- cgit v1.1 From 3e1f21121771ff6c3f9865b1184a07144eadc8d6 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 21 Jun 2011 20:51:09 +0000 Subject: Supress warning that command didn't complete when the parent bus thinks the card is gone. --- sys/dev/xl/if_xl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/xl/if_xl.c b/sys/dev/xl/if_xl.c index f1c1d02..355fa2d 100644 --- a/sys/dev/xl/if_xl.c +++ b/sys/dev/xl/if_xl.c @@ -334,7 +334,7 @@ xl_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) * only a finite amount of time to avoid getting caught in an * infinite loop. Normally this delay routine would be a macro, * but it isn't called during normal operation so we can afford - * to make it a function. + * to make it a function. Spress warning when card gone. */ static void xl_wait(struct xl_softc *sc) @@ -346,7 +346,7 @@ xl_wait(struct xl_softc *sc) break; } - if (i == XL_TIMEOUT) + if (i == XL_TIMEOUT && bus_child_present(sc->xl_dev)) device_printf(sc->xl_dev, "command never completed!\n"); } -- cgit v1.1 From 9bd4b3fa750e150be12f83324afa42ab889d6266 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 21 Jun 2011 20:52:55 +0000 Subject: Supress command completion failure warning when the card isn't present. Only call the bus to check if we actually do timeout so we don't affect the normal case (since this case needn't be optimized and this guards against all races). --- sys/dev/dc/if_dc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c index 772eede..b9567de 100644 --- a/sys/dev/dc/if_dc.c +++ b/sys/dev/dc/if_dc.c @@ -1385,7 +1385,7 @@ dc_netcfg_wait(struct dc_softc *sc) break; DELAY(10); } - if (i == DC_TIMEOUT) { + if (i == DC_TIMEOUT && bus_child_present(sc->dc_dev)) { if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc)) device_printf(sc->dc_dev, "%s: failed to force tx to idle state\n", __func__); -- cgit v1.1 From 5fdc59005b44cc624809b95e4d0e4d2d76ccf728 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Tue, 21 Jun 2011 21:07:33 +0000 Subject: Change the NFSv4 nfsuserd(8) daemon so that it doesn't preload the uid<->username mapping cache with an entry when another entry for that uid is already loaded. This fixes a case where the mapping of "toor" would replace "root" when the daemon was started, resulting in no mapping for "root" until the cache entry for "toor" timed out. The algorithm is inefficient, but since it is only done once when the daemon is started up, I don't think that's an issue. MFC after: 2 weeks --- usr.sbin/nfsuserd/nfsuserd.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/usr.sbin/nfsuserd/nfsuserd.c b/usr.sbin/nfsuserd/nfsuserd.c index 9dd6396..35e2849 100644 --- a/usr.sbin/nfsuserd/nfsuserd.c +++ b/usr.sbin/nfsuserd/nfsuserd.c @@ -76,6 +76,8 @@ static bool_t xdr_retval(XDR *, caddr_t); #define MAXNAME 1024 #define MAXNFSUSERD 20 #define DEFNFSUSERD 4 +#define MAXUSERMAX 100000 +#define MINUSERMAX 10 #define DEFUSERMAX 200 #define DEFUSERTIMEOUT (1 * 60) struct info { @@ -96,8 +98,8 @@ pid_t slaves[MAXNFSUSERD]; int main(int argc, char *argv[]) { - int i; - int error, len, mustfreeai = 0; + int i, j; + int error, fnd_dup, len, mustfreeai = 0, start_uidpos; struct nfsd_idargs nid; struct passwd *pwd; struct group *grp; @@ -107,6 +109,7 @@ main(int argc, char *argv[]) sigset_t signew; char hostname[MAXHOSTNAMELEN + 1], *cp; struct addrinfo *aip, hints; + static uid_t check_dups[MAXUSERMAX]; if (modfind("nfscommon") < 0) { /* Not present in kernel, try loading it */ @@ -163,9 +166,10 @@ main(int argc, char *argv[]) argc--; argv++; i = atoi(*argv); - if (i < 10 || i > 100000) { + if (i < MINUSERMAX || i > MAXUSERMAX) { fprintf(stderr, - "usermax %d out of range 10<->100000\n", i); + "usermax %d out of range %d<->%d\n", i, + MINUSERMAX, MAXUSERMAX); usage(); } nid.nid_usermax = i; @@ -326,8 +330,25 @@ main(int argc, char *argv[]) /* * Loop around adding all users. */ + start_uidpos = i; setpwent(); while (i < nid.nid_usermax && (pwd = getpwent())) { + fnd_dup = 0; + /* + * Yes, this is inefficient, but it is only done once when + * the daemon is started and will run in a fraction of a second + * for nid_usermax at 10000. If nid_usermax is cranked up to + * 100000, it will take several seconds, depending on the CPU. + */ + for (j = 0; j < (i - start_uidpos); j++) + if (check_dups[j] == pwd->pw_uid) { + /* Found another entry for uid, so skip it */ + fnd_dup = 1; + break; + } + if (fnd_dup != 0) + continue; + check_dups[i - start_uidpos] = pwd->pw_uid; nid.nid_uid = pwd->pw_uid; nid.nid_name = pwd->pw_name; nid.nid_namelen = strlen(pwd->pw_name); -- cgit v1.1 From d0e5d10dcf603e05285afe3e61104975b44bdbb3 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 21 Jun 2011 21:30:20 +0000 Subject: Fix build with ACPI_DEBUG defined. Submitted by: jkim Pointy hat to: jhb --- sys/dev/acpica/acpi_resource.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c index 5c103df..ce6732f 100644 --- a/sys/dev/acpica/acpi_resource.c +++ b/sys/dev/acpica/acpi_resource.c @@ -343,22 +343,23 @@ acpi_parse_resource(ACPI_RESOURCE *res, void *context) if (res->Data.Address.MinAddressFixed == ACPI_ADDRESS_FIXED && res->Data.Address.MaxAddressFixed == ACPI_ADDRESS_FIXED) { if (res->Data.Address.ResourceType == ACPI_MEMORY_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%x/%d\n", - name, min, length)); + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%jx/%ju\n", + name, (uintmax_t)min, (uintmax_t)length)); set->set_memory(dev, arc->context, min, length); } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%x/%d\n", name, - min, length)); + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx/%ju\n", name, + (uintmax_t)min, (uintmax_t)length)); set->set_ioport(dev, arc->context, min, length); } } else { if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/Memory 0x%x-0x%x/%d\n", - name, min, max, length)); + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, + "%s/Memory 0x%jx-0x%jx/%ju\n", name, (uintmax_t)min, + (uintmax_t)max, (uintmax_t)length)); set->set_memoryrange(dev, arc->context, min, max, length, gran); } else { - ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%x-0x%x/%d\n", - name, min, max, length)); + ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s/IO 0x%jx-0x%jx/%ju\n", + name, (uintmax_t)min, (uintmax_t)max, (uintmax_t)length)); set->set_iorange(dev, arc->context, min, max, length, gran); } } -- cgit v1.1 From 19f3f95131968b6bcdf843f415bbbe5fa64951f4 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 21 Jun 2011 22:16:04 +0000 Subject: My broken 'u' key scks! --- sys/dev/xl/if_xl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/xl/if_xl.c b/sys/dev/xl/if_xl.c index 355fa2d..559ef03 100644 --- a/sys/dev/xl/if_xl.c +++ b/sys/dev/xl/if_xl.c @@ -334,7 +334,7 @@ xl_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) * only a finite amount of time to avoid getting caught in an * infinite loop. Normally this delay routine would be a macro, * but it isn't called during normal operation so we can afford - * to make it a function. Spress warning when card gone. + * to make it a function. Supress warning when card gone. */ static void xl_wait(struct xl_softc *sc) -- cgit v1.1 From 87cfd8e26b2d81effe33a846a0676029cffa618e Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 21 Jun 2011 22:17:28 +0000 Subject: Really spell suppress the right way --- sys/dev/xl/if_xl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/xl/if_xl.c b/sys/dev/xl/if_xl.c index 559ef03..e09e434 100644 --- a/sys/dev/xl/if_xl.c +++ b/sys/dev/xl/if_xl.c @@ -334,7 +334,7 @@ xl_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) * only a finite amount of time to avoid getting caught in an * infinite loop. Normally this delay routine would be a macro, * but it isn't called during normal operation so we can afford - * to make it a function. Supress warning when card gone. + * to make it a function. Suppress warning when card gone. */ static void xl_wait(struct xl_softc *sc) -- cgit v1.1 From 20dad9c2b7ff51d2050fa8b4716475e4a6dead62 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 21 Jun 2011 22:45:31 +0000 Subject: Minor cleanup: o Consider No CIS a normal event and stop whining about it so much (too many cards are like this, espeically usb/firewire cards). o Add comments to the cis reading code. o Made the read from config space a smidge easier to read and eliminate a loop that can be done mathematically. --- sys/dev/cardbus/cardbus_cis.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c index 3352a56..ca1ef4b 100644 --- a/sys/dev/cardbus/cardbus_cis.c +++ b/sys/dev/cardbus/cardbus_cis.c @@ -369,6 +369,14 @@ decode_tuple_end(device_t cbdev, device_t child, int id, * Functions to read the a tuple from the card */ +/* + * Read CIS bytes out of the config space. We have to read it 4 bytes at a + * time and do the usual mask and shift to return the bytes. The standard + * defines the byte order to be little endian. pci_read_config converts it to + * host byte order. This is why we have no endian conversion functions: the + * shifts wind up being endian neutral. This is also why we avoid the obvious + * memcpy optimization. + */ static int cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start, uint32_t *off, int *tupleid, int *len, uint8_t *tupledata) @@ -379,12 +387,11 @@ cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start, loc = start + *off; - e = pci_read_config(child, loc - loc % 4, 4); - for (j = loc % 4; j > 0; j--) - e >>= 8; + e = pci_read_config(child, loc & ~0x3, 4); + e >>= 8 * (loc & 0x3); *len = 0; for (i = loc, j = -2; j < *len; j++, i++) { - if (i % 4 == 0) + if ((i & 0x3) == 0) e = pci_read_config(child, i, 4); if (j == -2) *tupleid = 0xff & e; @@ -398,6 +405,10 @@ cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start, return (0); } +/* + * Read the CIS data out of memroy. We indirect through the bus space + * routines to ensure proper byte ordering conversions when necessary. + */ static int cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start, uint32_t *off, int *tupleid, int *len, uint8_t *tupledata) @@ -580,7 +591,7 @@ cardbus_parse_cis(device_t cbdev, device_t child, expect_linktarget = TRUE; if ((start = pci_read_config(child, PCIR_CIS, 4)) == 0) { DEVPRINTF((cbdev, "Warning: CIS pointer is 0: (no CIS)\n")); - return (ENXIO); + return (0); } DEVPRINTF((cbdev, "CIS pointer is %#x\n", start)); off = 0; -- cgit v1.1 From cb19012ca64672139d8b24372b4bde0e2ee66d83 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Wed, 22 Jun 2011 02:11:42 +0000 Subject: The IOMMU is not involved for the storage bus. --- sys/powerpc/ps3/ps3bus.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/powerpc/ps3/ps3bus.c b/sys/powerpc/ps3/ps3bus.c index 2fe303d..a4f4a39 100644 --- a/sys/powerpc/ps3/ps3bus.c +++ b/sys/powerpc/ps3/ps3bus.c @@ -631,8 +631,7 @@ ps3bus_get_dma_tag(device_t dev, device_t child) struct ps3bus_softc *sc = device_get_softc(dev); int i, err, flags; - if (dinfo->bustype != PS3_BUSTYPE_SYSBUS && - dinfo->bustype != PS3_BUSTYPE_STORAGE) + if (dinfo->bustype != PS3_BUSTYPE_SYSBUS) return (bus_get_dma_tag(dev)); mtx_lock(&dinfo->iommu_mtx); -- cgit v1.1 From d62d61ee14efeb016aa2729993e5366dc0a08582 Mon Sep 17 00:00:00 2001 From: yongari Date: Wed, 22 Jun 2011 02:18:45 +0000 Subject: Remove link state change callback handler. There is no need to register both status change and link state change callbacks. Implement checking valid link in state change callback and poll active link state in vr_tick(). This allows immediate detection of lost link as well as protecting driver from frequent link flips during link renegotiation. taskq implementation was removed because driver now needs to poll link state in vr_tick(). While I'm here do not report current link state if interface is not running. Tested by: n_hibma MFC after: 1 week --- sys/dev/vr/if_vr.c | 47 ++++++++++++++++++++--------------------------- sys/dev/vr/if_vrreg.h | 1 - 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/sys/dev/vr/if_vr.c b/sys/dev/vr/if_vr.c index 906ee1c..1c2aac2 100644 --- a/sys/dev/vr/if_vr.c +++ b/sys/dev/vr/if_vr.c @@ -185,7 +185,6 @@ static int vr_miibus_readreg(device_t, int, int); static int vr_miibus_writereg(device_t, int, int, int); static void vr_miibus_statchg(device_t); -static void vr_link_task(void *, int); static void vr_cam_mask(struct vr_softc *, uint32_t, int); static int vr_cam_data(struct vr_softc *, int, int, uint8_t *); static void vr_set_filter(struct vr_softc *); @@ -226,7 +225,6 @@ static device_method_t vr_methods[] = { DEVMETHOD(miibus_readreg, vr_miibus_readreg), DEVMETHOD(miibus_writereg, vr_miibus_writereg), DEVMETHOD(miibus_statchg, vr_miibus_statchg), - DEVMETHOD(miibus_linkchg, vr_miibus_statchg), { NULL, NULL } }; @@ -290,22 +288,13 @@ vr_miibus_writereg(device_t dev, int phy, int reg, int data) return (0); } -static void -vr_miibus_statchg(device_t dev) -{ - struct vr_softc *sc; - - sc = device_get_softc(dev); - taskqueue_enqueue(taskqueue_swi, &sc->vr_link_task); -} - /* * In order to fiddle with the * 'full-duplex' and '100Mbps' bits in the netconfig register, we * first have to put the transmit and/or receive logic in the idle state. */ static void -vr_link_task(void *arg, int pending) +vr_miibus_statchg(device_t dev) { struct vr_softc *sc; struct mii_data *mii; @@ -313,22 +302,25 @@ vr_link_task(void *arg, int pending) int lfdx, mfdx; uint8_t cr0, cr1, fc; - sc = (struct vr_softc *)arg; - - VR_LOCK(sc); + sc = device_get_softc(dev); mii = device_get_softc(sc->vr_miibus); ifp = sc->vr_ifp; if (mii == NULL || ifp == NULL || - (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - VR_UNLOCK(sc); + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) return; - } - if (mii->mii_media_status & IFM_ACTIVE) { - if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) + sc->vr_link = 0; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: sc->vr_link = 1; - } else - sc->vr_link = 0; + break; + default: + break; + } + } if (sc->vr_link != 0) { cr0 = CSR_READ_1(sc, VR_CR0); @@ -384,11 +376,8 @@ vr_link_task(void *arg, int pending) "%s: Tx/Rx shutdown error -- resetting\n", __func__); sc->vr_flags |= VR_F_RESTART; - VR_UNLOCK(sc); - return; } } - VR_UNLOCK(sc); } @@ -621,7 +610,6 @@ vr_attach(device_t dev) mtx_init(&sc->vr_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); callout_init_mtx(&sc->vr_stat_callout, &sc->vr_mtx, 0); - TASK_INIT(&sc->vr_link_task, 0, vr_link_task, sc); SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0, @@ -841,7 +829,6 @@ vr_detach(device_t dev) vr_stop(sc); VR_UNLOCK(sc); callout_drain(&sc->vr_stat_callout); - taskqueue_drain(taskqueue_swi, &sc->vr_link_task); ether_ifdetach(ifp); } if (sc->vr_miibus) @@ -1559,6 +1546,8 @@ vr_tick(void *xsc) mii = device_get_softc(sc->vr_miibus); mii_tick(mii); + if (sc->vr_link == 0) + vr_miibus_statchg(sc->vr_dev); vr_watchdog(sc); callout_reset(&sc->vr_stat_callout, hz, vr_tick, sc); } @@ -2161,6 +2150,10 @@ vr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) sc = ifp->if_softc; mii = device_get_softc(sc->vr_miibus); VR_LOCK(sc); + if ((ifp->if_flags & IFF_UP) == 0) { + VR_UNLOCK(sc); + return; + } mii_pollstat(mii); VR_UNLOCK(sc); ifmr->ifm_active = mii->mii_media_active; diff --git a/sys/dev/vr/if_vrreg.h b/sys/dev/vr/if_vrreg.h index d686bdd..5e2b6b8 100644 --- a/sys/dev/vr/if_vrreg.h +++ b/sys/dev/vr/if_vrreg.h @@ -723,7 +723,6 @@ struct vr_softc { uint8_t vr_flags; /* See VR_F_* below */ #define VR_F_RESTART 0x01 /* Restart unit on next tick */ int vr_if_flags; - struct task vr_link_task; struct vr_chain_data vr_cdata; struct vr_ring_data vr_rdata; struct vr_statistics vr_stat; -- cgit v1.1 From 287623370e2ed80006fb7eba25f6eff7a36ac84f Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Wed, 22 Jun 2011 02:23:18 +0000 Subject: This is more complicated than I expected. Storage devices need the IOMMU set up, but must not use it. --- sys/powerpc/ps3/ps3bus.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sys/powerpc/ps3/ps3bus.c b/sys/powerpc/ps3/ps3bus.c index a4f4a39..88b4be2 100644 --- a/sys/powerpc/ps3/ps3bus.c +++ b/sys/powerpc/ps3/ps3bus.c @@ -631,7 +631,8 @@ ps3bus_get_dma_tag(device_t dev, device_t child) struct ps3bus_softc *sc = device_get_softc(dev); int i, err, flags; - if (dinfo->bustype != PS3_BUSTYPE_SYSBUS) + if (dinfo->bustype != PS3_BUSTYPE_SYSBUS && + dinfo->bustype != PS3_BUSTYPE_STORAGE) return (bus_get_dma_tag(dev)); mtx_lock(&dinfo->iommu_mtx); @@ -671,7 +672,15 @@ ps3bus_get_dma_tag(device_t dev, device_t child) NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE, 0, NULL, NULL, &dinfo->dma_tag); - bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo); + /* + * Note: storage devices have IOMMU mappings set up by the hypervisor, + * but use physical, non-translated addresses. The above IOMMU + * initialization is necessary for the hypervisor to be able to set up + * the mappings, but actual DMA mappings should not use the IOMMU + * routines. + */ + if (dinfo->bustype != PS3_BUSTYPE_STORAGE) + bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo); fail: mtx_unlock(&dinfo->iommu_mtx); -- cgit v1.1 From 927e352870db8c56ad0e654fa446f77f2930e20f Mon Sep 17 00:00:00 2001 From: dougb Date: Wed, 22 Jun 2011 06:27:32 +0000 Subject: I knew there was something funny about this line --- etc/rc.d/netwait | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/etc/rc.d/netwait b/etc/rc.d/netwait index d7a5184..1d3556a 100755 --- a/etc/rc.d/netwait +++ b/etc/rc.d/netwait @@ -14,7 +14,8 @@ . /etc/rc.subr name="netwait" -rc_var=`set_rcvar` +rcvar=`set_rcvar` + start_cmd="${name}_start" stop_cmd=":" -- cgit v1.1 From 5b5e9b6b99db5e50dca23adaf0b6f25a80936e79 Mon Sep 17 00:00:00 2001 From: glebius Date: Wed, 22 Jun 2011 08:20:01 +0000 Subject: One more braino from me. Pointy hat to: glebius Submitted by: Alexander V. Chernikov --- sbin/ipfw/nat.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c index ecb5d8a..efadeba 100644 --- a/sbin/ipfw/nat.c +++ b/sbin/ipfw/nat.c @@ -785,8 +785,9 @@ ipfw_config_nat(int ac, char **av) len += estimate_redir_port(&ac1, &av1); av1 += 2; ac1 -= 2; /* Skip optional remoteIP/port */ - if (ac1 != 0 && isdigit(**av1)) + if (ac1 != 0 && isdigit(**av1)) { av1++; ac1--; + } break; case TOK_REDIR_PROTO: if (ac1 < 2) @@ -795,10 +796,12 @@ ipfw_config_nat(int ac, char **av) len += sizeof(struct cfg_redir); av1 += 2; ac1 -= 2; /* Skip optional remoteIP/port */ - if (ac1 != 0 && isdigit(**av1)) + if (ac1 != 0 && isdigit(**av1)) { av1++; ac1--; - if (ac1 != 0 && isdigit(**av1)) + } + if (ac1 != 0 && isdigit(**av1)) { av1++; ac1--; + } break; default: errx(EX_DATAERR, "unrecognised option ``%s''", av1[-1]); -- cgit v1.1 From da0d2942ce08958ef4188446f468ba7dbc4d686e Mon Sep 17 00:00:00 2001 From: ae Date: Wed, 22 Jun 2011 09:55:28 +0000 Subject: Document PKT_ALIAS_SKIP_GLOBAL option. Submitted by: Alexander V. Chernikov --- sys/netinet/libalias/libalias.3 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3 index 31702e8..e441402 100644 --- a/sys/netinet/libalias/libalias.3 +++ b/sys/netinet/libalias/libalias.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 1, 2006 +.Dd June 22, 2011 .Dt LIBALIAS 3 .Os .Sh NAME @@ -257,6 +257,16 @@ Normal packet aliasing is not performed. See .Fn LibAliasProxyRule below for details. +.It Dv PKT_ALIAS_SKIP_GLOBAL +This option is used by +.Pa ipfw_nat +only. Specifying it as a flag to +.Fn LibAliasSetMode +has no effect. See section +.Sx NETWORK ADDRESS TRANSLATION +in +.Xr ipfw 8 +for more details. .El .Ed .Pp -- cgit v1.1 From a0627f2e3f8b11a06d848f46dcd73032ded3bf5f Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 22 Jun 2011 16:15:15 +0000 Subject: Add a helper routine to conditionally modify the start address of a resource allocation from an x86 Host-PCI bridge driver so that it can be reused by the ACPI Host-PCI bridge driver (and eventually the MPTable Host-PCI bridge driver) instead of duplicating the same logic. Note that this means that hw.acpi.host_mem_start is now replaced with the hw.pci.host_mem_start tunable that was already used in the non-ACPI case. This also removes hw.acpi.host_mem_start on ia64 where it was not applicable (the implementation was very x86-specific). While here, adjust the logic to apply the new start address on any "wildcard" allocation even if that allocation comes from a subset of the allowable address range. Reviewed by: imp (1) --- sys/amd64/pci/pci_bus.c | 54 ++++++++++++++++++++++++----------------- sys/dev/acpica/acpi_pcib_acpi.c | 26 +++----------------- sys/i386/pci/pci_bus.c | 54 ++++++++++++++++++++++++----------------- 3 files changed, 68 insertions(+), 66 deletions(-) diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c index 7c377ac..1b07a06 100644 --- a/sys/amd64/pci/pci_bus.c +++ b/sys/amd64/pci/pci_bus.c @@ -302,35 +302,45 @@ legacy_pcib_write_ivar(device_t dev, device_t child, int which, return ENOENT; } +/* + * Helper routine for x86 Host-PCI bridge driver resource allocation. + * This is used to adjust the start address of wildcard allocation + * requests to avoid low addresses that are known to be problematic. + * + * If no memory preference is given, use upper 32MB slot most BIOSes + * use for their memory window. This is typically only used on older + * laptops that don't have PCI busses behind a PCI bridge, so assuming + * > 32MB is likely OK. + * + * However, this can cause problems for other chipsets, so we make + * this tunable by hw.pci.host_mem_start. + */ SYSCTL_DECL(_hw_pci); -static unsigned long legacy_host_mem_start = 0x80000000; -TUNABLE_ULONG("hw.pci.host_mem_start", &legacy_host_mem_start); -SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, - &legacy_host_mem_start, 0x80000000, - "Limit the host bridge memory to being above this address. Must be\n\ -set at boot via a tunable."); +static unsigned long host_mem_start = 0x80000000; +TUNABLE_ULONG("hw.pci.host_mem_start", &host_mem_start); +SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start, + 0, "Limit the host bridge memory to being above this address."); + +u_long +hostb_alloc_start(int type, u_long start, u_long end, u_long count) +{ + + if (start + count - 1 != end) { + if (type == SYS_RES_MEMORY && start < host_mem_start) + start = host_mem_start; + if (type == SYS_RES_IOPORT && start < 0x1000) + start = 0x1000; + } + return (start); +} struct resource * legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - /* - * If no memory preference is given, use upper 32MB slot most - * bioses use for their memory window. Typically other bridges - * before us get in the way to assert their preferences on memory. - * Hardcoding like this sucks, so a more MD/MI way needs to be - * found to do it. This is typically only used on older laptops - * that don't have pci busses behind pci bridge, so assuming > 32MB - * is liekly OK. - * - * However, this can cause problems for other chipsets, so we make - * this tunable by hw.pci.host_mem_start. - */ - if (type == SYS_RES_MEMORY && start == 0UL && end == ~0UL) - start = legacy_host_mem_start; - if (type == SYS_RES_IOPORT && start == 0UL && end == ~0UL) - start = 0x1000; + + start = hostb_alloc_start(type, start, end, count); return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); } diff --git a/sys/dev/acpica/acpi_pcib_acpi.c b/sys/dev/acpica/acpi_pcib_acpi.c index e4efeff..73b2f70 100644 --- a/sys/dev/acpica/acpi_pcib_acpi.c +++ b/sys/dev/acpica/acpi_pcib_acpi.c @@ -357,32 +357,14 @@ acpi_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data)); } -static u_long acpi_host_mem_start = 0x80000000; -TUNABLE_ULONG("hw.acpi.host_mem_start", &acpi_host_mem_start); - struct resource * acpi_pcib_acpi_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - /* - * If no memory preference is given, use upper 32MB slot most - * bioses use for their memory window. Typically other bridges - * before us get in the way to assert their preferences on memory. - * Hardcoding like this sucks, so a more MD/MI way needs to be - * found to do it. This is typically only used on older laptops - * that don't have pci busses behind pci bridge, so assuming > 32MB - * is likely OK. - * - * PCI-PCI bridges may allocate smaller ranges for their windows, - * but the heuristics here should apply to those, so we allow - * several different end addresses. - */ - if (type == SYS_RES_MEMORY && start == 0UL && (end == ~0UL || - end == 0xffffffff)) - start = acpi_host_mem_start; - if (type == SYS_RES_IOPORT && start == 0UL && (end == ~0UL || - end == 0xffff || end == 0xffffffff)) - start = 0x1000; + +#if defined(__i386__) || defined(__amd64__) + start = hostb_alloc_start(type, start, end, count); +#endif return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); } diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index 61dab3f..7b457bd 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -519,35 +519,45 @@ legacy_pcib_write_ivar(device_t dev, device_t child, int which, return ENOENT; } +/* + * Helper routine for x86 Host-PCI bridge driver resource allocation. + * This is used to adjust the start address of wildcard allocation + * requests to avoid low addresses that are known to be problematic. + * + * If no memory preference is given, use upper 32MB slot most BIOSes + * use for their memory window. This is typically only used on older + * laptops that don't have PCI busses behind a PCI bridge, so assuming + * > 32MB is likely OK. + * + * However, this can cause problems for other chipsets, so we make + * this tunable by hw.pci.host_mem_start. + */ SYSCTL_DECL(_hw_pci); -static unsigned long legacy_host_mem_start = 0x80000000; -TUNABLE_ULONG("hw.pci.host_mem_start", &legacy_host_mem_start); -SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, - &legacy_host_mem_start, 0x80000000, - "Limit the host bridge memory to being above this address. Must be\n\ -set at boot via a tunable."); +static unsigned long host_mem_start = 0x80000000; +TUNABLE_ULONG("hw.pci.host_mem_start", &host_mem_start); +SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start, + 0, "Limit the host bridge memory to being above this address."); + +u_long +hostb_alloc_start(int type, u_long start, u_long end, u_long count) +{ + + if (start + count - 1 != end) { + if (type == SYS_RES_MEMORY && start < host_mem_start) + start = host_mem_start; + if (type == SYS_RES_IOPORT && start < 0x1000) + start = 0x1000; + } + return (start); +} struct resource * legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - /* - * If no memory preference is given, use upper 32MB slot most - * bioses use for their memory window. Typically other bridges - * before us get in the way to assert their preferences on memory. - * Hardcoding like this sucks, so a more MD/MI way needs to be - * found to do it. This is typically only used on older laptops - * that don't have pci busses behind pci bridge, so assuming > 32MB - * is liekly OK. - * - * However, this can cause problems for other chipsets, so we make - * this tunable by hw.pci.host_mem_start. - */ - if (type == SYS_RES_MEMORY && start == 0UL && end == ~0UL) - start = legacy_host_mem_start; - if (type == SYS_RES_IOPORT && start == 0UL && end == ~0UL) - start = 0x1000; + + start = hostb_alloc_start(type, start, end, count); return (bus_generic_alloc_resource(dev, child, type, rid, start, end, count, flags)); } -- cgit v1.1 From 6da60ac39ebac7fcdb953979962ecb5f7658196a Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 22 Jun 2011 16:40:45 +0000 Subject: Set negative quality to TSC timecounter when C3 state is enabled for Intel processors unless the invariant TSC bit of CPUID is set. Intel processors may stop incrementing TSC when DPSLP# pin is asserted, according to Intel processor manuals, i. e., TSC timecounter is useless if the processor can enter deep sleep state (C3/C4). This problem was accidentally uncovered by r222869, which increased timecounter quality of P-state invariant TSC, e.g., for Core2 Duo T5870 (Family 6, Model f) and Atom N270 (Family 6, Model 1c). Reported by: Fabian Keil (freebsd-listen at fabiankeil dot de) Ian FREISLICH (ianf at clue dot co dot za) Tested by: Fabian Keil (freebsd-listen at fabiankeil dot de) - Core2 Duo T5870 (C3 state available/enabled) jkim - Xeon X5150 (C3 state unavailable) --- sys/dev/acpica/acpi_cpu.c | 2 ++ sys/kern/kern_clocksource.c | 1 + sys/sys/systm.h | 1 + sys/x86/x86/tsc.c | 13 +++++++++++++ 4 files changed, 17 insertions(+) diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c index 8cb6858..583b548 100644 --- a/sys/dev/acpica/acpi_cpu.c +++ b/sys/dev/acpica/acpi_cpu.c @@ -856,6 +856,8 @@ acpi_cpu_cx_list(struct acpi_cpu_softc *sc) sbuf_printf(&sb, "C%d/%d ", i + 1, sc->cpu_cx_states[i].trans_lat); if (sc->cpu_cx_states[i].type < ACPI_STATE_C3) sc->cpu_non_c3 = i; + else + cpu_can_deep_sleep = 1; } sbuf_trim(&sb); sbuf_finish(&sb); diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c index dd8bab5..ecfd408 100644 --- a/sys/kern/kern_clocksource.c +++ b/sys/kern/kern_clocksource.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); cyclic_clock_func_t cyclic_clock_func = NULL; #endif +int cpu_can_deep_sleep = 0; /* C3 state is available. */ int cpu_disable_deep_sleep = 0; /* Timer dies in C3. */ static void setuptimer(void); diff --git a/sys/sys/systm.h b/sys/sys/systm.h index e563a5a..35d34e4 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -253,6 +253,7 @@ void cpu_startprofclock(void); void cpu_stopprofclock(void); void cpu_idleclock(void); void cpu_activeclock(void); +extern int cpu_can_deep_sleep; extern int cpu_disable_deep_sleep; int cr_cansee(struct ucred *u1, struct ucred *u2); diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c index 9501eee..5f17f62 100644 --- a/sys/x86/x86/tsc.c +++ b/sys/x86/x86/tsc.c @@ -444,6 +444,19 @@ init_TSC_tc(void) goto init; } + /* + * We cannot use the TSC if it stops incrementing in deep sleep. + * Currently only Intel CPUs are known for this problem unless + * the invariant TSC bit is set. + */ + if (cpu_can_deep_sleep && cpu_vendor_id == CPU_VENDOR_INTEL && + (amd_pminfo & AMDPM_TSC_INVARIANT) == 0) { + tsc_timecounter.tc_quality = -1000; + if (bootverbose) + printf("TSC timecounter disabled: C3 enabled.\n"); + goto init; + } + #ifdef SMP /* * We can not use the TSC in SMP mode unless the TSCs on all CPUs are -- cgit v1.1 From b2d6c3b58f107ca6a03cdd7de9990af3be053ca0 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 22 Jun 2011 17:55:16 +0000 Subject: Use uintXX_t instead of u_intXX_t. --- sys/amd64/pci/pci_bus.c | 6 +++--- sys/i386/pci/pci_bus.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c index 1b07a06..6d58575 100644 --- a/sys/amd64/pci/pci_bus.c +++ b/sys/amd64/pci/pci_bus.c @@ -135,7 +135,7 @@ static void legacy_pcib_identify(driver_t *driver, device_t parent) { int bus, slot, func; - u_int8_t hdrtype; + uint8_t hdrtype; int found = 0; int pcifunchigh; int found824xx = 0; @@ -178,8 +178,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent) /* * Read the IDs and class from the device. */ - u_int32_t id; - u_int8_t class, subclass, busnum; + uint32_t id; + uint8_t class, subclass, busnum; const char *s; device_t *devs; int ndevs, i; diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index 7b457bd..c247180 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -62,7 +62,7 @@ legacy_pcib_maxslots(device_t dev) /* read configuration space register */ -u_int32_t +uint32_t legacy_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int bytes) { @@ -73,7 +73,7 @@ legacy_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, void legacy_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, u_int32_t data, int bytes) + u_int reg, uint32_t data, int bytes) { pci_cfgregwrite(bus, slot, func, reg, data, bytes); } @@ -342,7 +342,7 @@ static void legacy_pcib_identify(driver_t *driver, device_t parent) { int bus, slot, func; - u_int8_t hdrtype; + uint8_t hdrtype; int found = 0; int pcifunchigh; int found824xx = 0; @@ -385,8 +385,8 @@ legacy_pcib_identify(driver_t *driver, device_t parent) /* * Read the IDs and class from the device. */ - u_int32_t id; - u_int8_t class, subclass, busnum; + uint32_t id; + uint8_t class, subclass, busnum; const char *s; device_t *devs; int ndevs, i; -- cgit v1.1 From c89f3f1a1b241c07b233d2e155ef2c637032ac63 Mon Sep 17 00:00:00 2001 From: trasz Date: Wed, 22 Jun 2011 17:59:53 +0000 Subject: Cosmetic fixes; mostly s/file system/filesystem/g and removing weird indent from messages. --- sbin/growfs/growfs.8 | 42 +++++++++++++++++++++--------------------- sbin/growfs/growfs.c | 50 +++++++++++++++++++++++++------------------------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/sbin/growfs/growfs.8 b/sbin/growfs/growfs.8 index 2e90c79..037814d 100644 --- a/sbin/growfs/growfs.8 +++ b/sbin/growfs/growfs.8 @@ -37,12 +37,12 @@ .\" $TSHeader: src/sbin/growfs/growfs.8,v 1.3 2000/12/12 19:31:00 tomsoft Exp $ .\" $FreeBSD$ .\" -.Dd May 8, 2011 +.Dd June 22, 2011 .Dt GROWFS 8 .Os .Sh NAME .Nm growfs -.Nd grow size of an existing UFS file system +.Nd expand an existing UFS filesystem .Sh SYNOPSIS .Nm .Op Fl Ny @@ -58,26 +58,26 @@ Before starting .Nm the disk must be labeled to a bigger size using .Xr bsdlabel 8 . -If you wish to grow a file system beyond the boundary of -the slice it resides in, you must re-size the slice using -.Xr fdisk 8 +If you wish to grow a filesystem beyond the boundary of +the slice it resides in, you must resize the slice using +.Xr gpart 8 before running .Nm . If you are using volumes you must enlarge them by using -.Xr vinum 8 . +.Xr gvinum 8 . The .Nm -utility extends the size of the file system on the specified special file. +utility extends the size of the filesystem on the specified special file. Currently .Nm -can only enlarge unmounted file systems. -Do not try enlarging a mounted file system, your system may panic and you will -not be able to use the file system any longer. +can only enlarge unmounted filesystems. +Do not try enlarging a mounted filesystem, your system may panic and you will +not be able to use the filesystem any longer. Most of the .Xr newfs 8 options cannot be changed by .Nm . -In fact, you can only increase the size of the file system. +In fact, you can only increase the size of the filesystem. Use .Xr tunefs 8 for other changes. @@ -86,8 +86,8 @@ The following options are available: .Bl -tag -width indent .It Fl N .Dq Test mode . -Causes the new file system parameters to be printed out without actually -enlarging the file system. +Causes the new filesystem parameters to be printed out without actually +enlarging the filesystem. .It Fl y .Dq Expert mode . Usually @@ -102,12 +102,12 @@ So use this option with great care! .It Fl s Ar size Determines the .Ar size -of the file system after enlarging in sectors. +of the filesystem after enlarging in sectors. This value defaults to the size of the raw partition specified in .Ar special (in other words, .Nm -will enlarge the file system to the size of the entire partition). +will enlarge the filesystem to the size of the entire partition). .El .Sh EXAMPLES .Dl growfs -s 4194304 /dev/vinum/testvol @@ -119,12 +119,12 @@ up to 2GB if there is enough space in .Sh SEE ALSO .Xr bsdlabel 8 , .Xr dumpfs 8 , -.Xr fdisk 8 , .Xr ffsinfo 8 , .Xr fsck 8 , +.Xr gpart 8 , .Xr newfs 8 , .Xr tunefs 8 , -.Xr vinum 8 +.Xr gvinum 8 .Sh HISTORY The .Nm @@ -144,12 +144,12 @@ There may be cases on .Fx 3.x only, when .Nm -does not recognize properly whether or not the file system is mounted and +does not recognize properly whether or not the filesystem is mounted and exits with an error message. Then please use .Nm .Fl y -if you are sure that the file system is not mounted. +if you are sure that the filesystem is not mounted. It is also recommended to always use .Xr fsck 8 after enlarging (just to be on the safe side). @@ -183,8 +183,8 @@ on the first cylinder group to verify that in the CYLINDER SUMMARY (internal cs) of the CYLINDER GROUP .Em cgr0 has enough blocks. -As a rule of thumb for default file system parameters one block is needed for -every 2 GB of total file system size. +As a rule of thumb for default filesystem parameters one block is needed for +every 2 GB of total filesystem size. .Pp Normally .Nm diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index 45a7237..76a2841 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -160,7 +160,7 @@ static void get_dev_size(int, int *); /* ************************************************************ growfs ***** */ /* - * Here we actually start growing the file system. We basically read the + * Here we actually start growing the filesystem. We basically read the * cylinder summary from the first cylinder group as we want to update * this on the fly during our various operations. First we handle the * changes in the former last cylinder group. Afterwards we create all new @@ -231,7 +231,7 @@ growfs(int fsi, int fso, unsigned int Nflag) updjcg(osblock.fs_ncg-1, modtime, fsi, fso, Nflag); /* - * Dump out summary information about file system. + * Dump out summary information about filesystem. */ # define B2MBFACTOR (1 / (1024.0 * 1024.0)) printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n", @@ -435,7 +435,7 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag) if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) { /* * This should never happen as we would have had that panic - * already on file system creation + * already on filesystem creation */ errx(37, "panic: cylinder group too big"); } @@ -446,7 +446,7 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag) acg.cg_cs.cs_nifree--; } /* - * For the old file system, we have to initialize all the inodes. + * For the old filesystem, we have to initialize all the inodes. */ if (sblock.fs_magic == FS_UFS1_MAGIC) { bzero(iobuf, sblock.fs_bsize); @@ -670,7 +670,7 @@ cond_bl_upd(ufs2_daddr_t *block, struct gfs_bpp *field, int fsi, int fso, /* ************************************************************ updjcg ***** */ /* * Here we do all needed work for the former last cylinder group. It has to be - * changed in any case, even if the file system ended exactly on the end of + * changed in any case, even if the filesystem ended exactly on the end of * this group, as there is some slightly inconsistent handling of the number * of cylinders in the cylinder group. We start again by reading the cylinder * group from disk. If the last block was not fully available, we first handle @@ -780,7 +780,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag) * the rotational layout tables and the cluster summary. This is * also done per fragment for the first new block if the old file * system end was not on a block boundary, per fragment for the new - * last block if the new file system end is not on a block boundary, + * last block if the new filesystem end is not on a block boundary, * and per block for all space in between. * * Handle the first new block here if it was partially available @@ -804,7 +804,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag) /* * Check if the fragment just created could join an * already existing fragment at the former end of the - * file system. + * filesystem. */ if(isblock(&sblock, cg_blksfree(&acg), ((osblock.fs_size - cgbase(&sblock, cylno))/ @@ -931,7 +931,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag) * Option (1) is considered to be less intrusive to the structure of the file- * system. So we try to stick to that whenever possible. If there is not enough * space in the cylinder group containing the cylinder summary we have to use - * method (2). In case of active snapshots in the file system we probably can + * method (2). In case of active snapshots in the filesystem we probably can * completely avoid implementing copy on write if we stick to method (2) only. */ static void @@ -1287,7 +1287,7 @@ updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag) /* * No cluster handling is needed here, as there was at least * one fragment in use by the cylinder summary in the old - * file system. + * filesystem. * No block-free counter handling here as this block was not * a free block. */ @@ -1597,7 +1597,7 @@ wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) /* * Here we allocate a free block in the current cylinder group. It is assumed, * that acg contains the current cylinder group. As we may take a block from - * somewhere in the file system we have to handle cluster summary here. + * somewhere in the filesystem we have to handle cluster summary here. */ static ufs2_daddr_t alloc(void) @@ -1939,9 +1939,9 @@ get_dev_size(int fd, int *size) /* ************************************************************** main ***** */ /* * growfs(8) is a utility which allows to increase the size of an existing - * ufs file system. Currently this can only be done on unmounted file system. + * ufs filesystem. Currently this can only be done on unmounted filesystem. * It recognizes some command line options to specify the new desired size, - * and it does some basic checkings. The old file system size is determined + * and it does some basic checkings. The old filesystem size is determined * and after some more checks like we can really access the new last block * on the disk etc. we calculate the new parameters for the superblock. After * having done this we just call growfs() which will do the work. Before @@ -1953,11 +1953,11 @@ get_dev_size(int fd, int *size) * are lucky, then we only have to handle our blocks to be relocated in that * way. * Also we have to consider in what order we actually update the critical - * data structures of the file system to make sure, that in case of a disaster + * data structures of the filesystem to make sure, that in case of a disaster * fsck(8) is still able to restore any lost data. * The foreseen last step then will be to provide for growing even mounted - * file systems. There we have to extend the mount() system call to provide - * userland access to the file system locking facility. + * filesystems. There we have to extend the mount() system call to provide + * userland access to the filesystem locking facility. */ int main(int argc, char **argv) @@ -2088,7 +2088,7 @@ main(int argc, char **argv) } /* - * Check if that partition is suitable for growing a file system. + * Check if that partition is suitable for growing a filesystem. */ if (p_size < 1) { errx(1, "partition is unavailable"); @@ -2146,8 +2146,8 @@ main(int argc, char **argv) if(ExpertFlag == 0) { for(j=0; j Date: Wed, 22 Jun 2011 18:02:28 +0000 Subject: Advertise growfs(8) a little better. --- sbin/newfs/newfs.8 | 3 ++- sbin/tunefs/tunefs.8 | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sbin/newfs/newfs.8 b/sbin/newfs/newfs.8 index 9d454cf..7cfdfd1 100644 --- a/sbin/newfs/newfs.8 +++ b/sbin/newfs/newfs.8 @@ -28,7 +28,7 @@ .\" @(#)newfs.8 8.6 (Berkeley) 5/3/95 .\" $FreeBSD$ .\" -.Dd May 25, 2011 +.Dd June 22, 2011 .Dt NEWFS 8 .Os .Sh NAME @@ -297,6 +297,7 @@ on file systems that contain many small files. .Xr dumpfs 8 , .Xr fsck 8 , .Xr gjournal 8 , +.Xr growfs 8 , .Xr makefs 8 , .Xr mount 8 , .Xr tunefs 8 , diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8 index 3b4e944..5b522e5 100644 --- a/sbin/tunefs/tunefs.8 +++ b/sbin/tunefs/tunefs.8 @@ -28,7 +28,7 @@ .\" @(#)tunefs.8 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" -.Dd May 8, 2011 +.Dd June 22, 2011 .Dt TUNEFS 8 .Os .Sh NAME @@ -165,6 +165,7 @@ specified mount point. .Xr fs 5 , .Xr dumpfs 8 , .Xr gjournal 8 , +.Xr growfs 8 , .Xr newfs 8 .Rs .%A M. McKusick -- cgit v1.1 From 3fa22c485f3792c67488fb38ae72a90e05bb7a25 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 22 Jun 2011 18:48:07 +0000 Subject: Oops, missed these in 223424. Reported by: jkim --- sys/amd64/include/pci_cfgreg.h | 1 + sys/i386/include/pci_cfgreg.h | 1 + 2 files changed, 2 insertions(+) diff --git a/sys/amd64/include/pci_cfgreg.h b/sys/amd64/include/pci_cfgreg.h index 7588282..0358e79 100644 --- a/sys/amd64/include/pci_cfgreg.h +++ b/sys/amd64/include/pci_cfgreg.h @@ -37,6 +37,7 @@ #define CONF1_ENABLE_MSK1 0x80000001ul #define CONF1_ENABLE_RES1 0x80000000ul +u_long hostb_alloc_start(int type, u_long start, u_long end, u_long count); int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus); int pci_cfgregopen(void); u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); diff --git a/sys/i386/include/pci_cfgreg.h b/sys/i386/include/pci_cfgreg.h index bc72418..6995971 100644 --- a/sys/i386/include/pci_cfgreg.h +++ b/sys/i386/include/pci_cfgreg.h @@ -43,6 +43,7 @@ #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e +u_long hostb_alloc_start(int type, u_long start, u_long end, u_long count); int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus); int pci_cfgregopen(void); u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); -- cgit v1.1 From 4bd1849e7f983e321378d18d4bad3f0b4660590a Mon Sep 17 00:00:00 2001 From: trasz Date: Wed, 22 Jun 2011 19:14:49 +0000 Subject: Add LOGIN_SETCPUMASK and LOGIN_SETLOGINCLASS to the setusercontext(3) calls in ftpd(8). --- libexec/ftpd/ftpd.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 21c218e..5894f3c 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -1191,9 +1191,9 @@ end_login(void) ftpd_logwtmp(wtmpid, NULL, NULL); pw = NULL; #ifdef LOGIN_CAP - setusercontext(NULL, getpwuid(0), 0, - LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK| - LOGIN_SETMAC); + setusercontext(NULL, getpwuid(0), 0, LOGIN_SETALL & ~(LOGIN_SETLOGIN | + LOGIN_SETUSER | LOGIN_SETGROUP | LOGIN_SETPATH | + LOGIN_SETENV)); #endif #ifdef USE_PAM if (pamh) { @@ -1465,9 +1465,8 @@ skip: return; } } - setusercontext(lc, pw, 0, - LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY| - LOGIN_SETRESOURCES|LOGIN_SETUMASK|LOGIN_SETMAC); + setusercontext(lc, pw, 0, LOGIN_SETALL & + ~(LOGIN_SETUSER | LOGIN_SETPATH | LOGIN_SETENV)); #else setlogin(pw->pw_name); (void) initgroups(pw->pw_name, pw->pw_gid); -- cgit v1.1 From 0a8537fb6af36d227389d693dc514cbd503ba043 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Wed, 22 Jun 2011 19:47:45 +0000 Subject: Fix the new NFSv4 client so that it uses the same uid as was used for doing a mount when performing system operations on AUTH_SYS mounts. This resolved an issue when mounting a Linux server. Found during testing at the recent NFSv4 interoperability Bakeathon. MFC after: 2 weeks --- sys/fs/nfs/nfs_commonkrpc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index df23e49..c34ea87 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -526,6 +526,20 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp, else secflavour = RPCSEC_GSS_KRB5; srv_principal = NFSMNT_SRVKRBNAME(nmp); + } else if (nmp != NULL && !NFSHASKERB(nmp) && + nd->nd_procnum != NFSPROC_NULL && + (nd->nd_flag & ND_USEGSSNAME) != 0) { + /* + * Use the uid that did the mount when the RPC is doing + * NFSv4 system operations, as indicated by the + * ND_USEGSSNAME flag, for the AUTH_SYS case. + */ + saved_uid = cred->cr_uid; + if (nmp->nm_uid != (uid_t)-1) + cred->cr_uid = nmp->nm_uid; + else + cred->cr_uid = 0; + set_uid = 1; } if (nmp != NULL) { -- cgit v1.1 From 5c101cd76879e8bb9585cf791002fb61ca6bb0e7 Mon Sep 17 00:00:00 2001 From: ae Date: Wed, 22 Jun 2011 20:00:27 +0000 Subject: Export AddLink() function from libalias. It can be used when custom alias address needs to be specified. Add inbound handler to the alias_ftp module. It helps handle active FTP transfer mode for the case with external clients and FTP server behind NAT. Fix passive FTP transfer case for server behind NAT using redirect with external IP address different from NAT ip address. PR: kern/157957 Submitted by: Alexander V. Chernikov --- sys/netinet/libalias/alias_db.c | 24 ++----- sys/netinet/libalias/alias_ftp.c | 124 ++++++++++++++++++++++++++++++------- sys/netinet/libalias/alias_local.h | 7 +++ sys/netinet/libalias/libalias.3 | 11 ++++ 4 files changed, 127 insertions(+), 39 deletions(-) diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c index 9b30793..4e0837f 100644 --- a/sys/netinet/libalias/alias_db.c +++ b/sys/netinet/libalias/alias_db.c @@ -552,10 +552,6 @@ static void IncrementalCleanup(struct libalias *); static void DeleteLink(struct alias_link *); static struct alias_link * -AddLink(struct libalias *, struct in_addr, struct in_addr, struct in_addr, - u_short, u_short, int, int); - -static struct alias_link * ReLink(struct alias_link *, struct in_addr, struct in_addr, struct in_addr, u_short, u_short, int, int); @@ -572,9 +568,6 @@ static struct alias_link * #define ALIAS_PORT_MASK_EVEN 0x07ffe #define GET_NEW_PORT_MAX_ATTEMPTS 20 -#define GET_ALIAS_PORT -1 -#define GET_ALIAS_ID GET_ALIAS_PORT - #define FIND_EVEN_ALIAS_BASE 1 /* GetNewPort() allocates port numbers. Note that if a port number @@ -937,17 +930,12 @@ DeleteLink(struct alias_link *lnk) } -static struct alias_link * -AddLink(struct libalias *la, struct in_addr src_addr, - struct in_addr dst_addr, - struct in_addr alias_addr, - u_short src_port, - u_short dst_port, - int alias_port_param, /* if less than zero, alias */ - int link_type) -{ /* port will be automatically *//* chosen. - * If greater than */ - u_int start_point; /* zero, equal to alias port */ +struct alias_link * +AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, + struct in_addr alias_addr, u_short src_port, u_short dst_port, + int alias_port_param, int link_type) +{ + u_int start_point; struct alias_link *lnk; LIBALIAS_LOCK_ASSERT(la); diff --git a/sys/netinet/libalias/alias_ftp.c b/sys/netinet/libalias/alias_ftp.c index ef0e52c..8e7d05b 100644 --- a/sys/netinet/libalias/alias_ftp.c +++ b/sys/netinet/libalias/alias_ftp.c @@ -100,38 +100,68 @@ __FBSDID("$FreeBSD$"); #define FTP_CONTROL_PORT_NUMBER 21 static void -AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *, - int maxpacketsize); +AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *, + int maxpacketsize); +static void +AliasHandleFtpIn(struct libalias *, struct ip *, struct alias_link *); -static int -fingerprint(struct libalias *la, struct alias_data *ah) +static int +fingerprint_out(struct libalias *la, struct alias_data *ah) { - if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || - ah->maxpktsize == 0) + if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL || + ah->maxpktsize == 0) return (-1); - if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER - || ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER) + if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER || + ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER) return (0); return (-1); } -static int -protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) +static int +fingerprint_in(struct libalias *la, struct alias_data *ah) +{ + + if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL) + return (-1); + if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER || + ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER) + return (0); + return (-1); +} + +static int +protohandler_out(struct libalias *la, struct ip *pip, struct alias_data *ah) { - + AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize); return (0); } + +static int +protohandler_in(struct libalias *la, struct ip *pip, struct alias_data *ah) +{ + + AliasHandleFtpIn(la, pip, ah->lnk); + return (0); +} + struct proto_handler handlers[] = { - { - .pri = 80, - .dir = OUT, - .proto = TCP, - .fingerprint = &fingerprint, - .protohandler = &protohandler - }, + { + .pri = 80, + .dir = OUT, + .proto = TCP, + .fingerprint = &fingerprint_out, + .protohandler = &protohandler_out + }, + { + .pri = 80, + .dir = IN, + .proto = TCP, + .fingerprint = &fingerprint_in, + .protohandler = &protohandler_in + }, { EOH } }; @@ -256,6 +286,57 @@ AliasHandleFtpOut( } } +static void +AliasHandleFtpIn(struct libalias *la, + struct ip *pip, /* IP packet to examine/patch */ + struct alias_link *lnk) /* The link to go through (aliased port) */ +{ + int hlen, tlen, dlen, pflags; + char *sptr; + struct tcphdr *tc; + + /* Calculate data length of TCP packet */ + tc = (struct tcphdr *)ip_next(pip); + hlen = (pip->ip_hl + tc->th_off) << 2; + tlen = ntohs(pip->ip_len); + dlen = tlen - hlen; + + /* Place string pointer and beginning of data */ + sptr = (char *)pip; + sptr += hlen; + + /* + * Check that data length is not too long and previous message was + * properly terminated with CRLF. + */ + pflags = GetProtocolFlags(lnk); + if (dlen <= MAX_MESSAGE_SIZE && (pflags & WAIT_CRLF) == 0 && + ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER && + (ParseFtpPortCommand(la, sptr, dlen) != 0 || + ParseFtpEprtCommand(la, sptr, dlen) != 0)) { + /* + * Alias active mode client requesting data from server + * behind NAT. We need to alias server->client connection + * to external address client is connecting to. + */ + AddLink(la, GetOriginalAddress(lnk), la->true_addr, + GetAliasAddress(lnk), htons(FTP_CONTROL_PORT_NUMBER - 1), + htons(la->true_port), GET_ALIAS_PORT, IPPROTO_TCP); + } + /* Track the msgs which are CRLF term'd for PORT/PASV FW breach */ + if (dlen) { + sptr = (char *)pip; /* start over at beginning */ + tlen = ntohs(pip->ip_len); /* recalc tlen, pkt may + * have grown. + */ + if (sptr[tlen - 2] == '\r' && sptr[tlen - 1] == '\n') + pflags &= ~WAIT_CRLF; + else + pflags |= WAIT_CRLF; + SetProtocolFlags(lnk, pflags); + } +} + static int ParseFtpPortCommand(struct libalias *la, char *sptr, int dlen) { @@ -576,9 +657,10 @@ NewFtpMessage(struct libalias *la, struct ip *pip, if (la->true_port < IPPORT_RESERVED) return; -/* Establish link to address and port found in FTP control message. */ - ftp_lnk = FindUdpTcpOut(la, la->true_addr, GetDestAddress(lnk), - htons(la->true_port), 0, IPPROTO_TCP, 1); + /* Establish link to address and port found in FTP control message. */ + ftp_lnk = AddLink(la, la->true_addr, GetDestAddress(lnk), + GetAliasAddress(lnk), htons(la->true_port), 0, GET_ALIAS_PORT, + IPPROTO_TCP); if (ftp_lnk != NULL) { int slen, hlen, tlen, dlen; diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h index e201394..c291a37 100644 --- a/sys/netinet/libalias/alias_local.h +++ b/sys/netinet/libalias/alias_local.h @@ -67,6 +67,9 @@ #define LINK_TABLE_OUT_SIZE 4001 #define LINK_TABLE_IN_SIZE 4001 +#define GET_ALIAS_PORT -1 +#define GET_ALIAS_ID GET_ALIAS_PORT + struct proxy_entry; struct libalias { @@ -249,6 +252,10 @@ DifferentialChecksum(u_short * _cksum, void * _new, void * _old, int _n); /* Internal data access */ struct alias_link * +AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, + struct in_addr alias_addr, u_short src_port, u_short dst_port, + int alias_param, int link_type); +struct alias_link * FindIcmpIn(struct libalias *la, struct in_addr _dst_addr, struct in_addr _alias_addr, u_short _id_alias, int _create); struct alias_link * diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3 index e441402..fb63a4c 100644 --- a/sys/netinet/libalias/libalias.3 +++ b/sys/netinet/libalias/libalias.3 @@ -824,6 +824,17 @@ argument is the pointer to a header fragment used as a template, and is the pointer to the packet to be de-aliased. .Ed .Sh MISCELLANEOUS FUNCTIONS +.Ft struct alias_link * +.Fn AddLink "struct libalias *" "struct in_addr src_addr" "struct in_addr dst_addr" \ +"struct in_addr alias_addr" "u_short src_port" "u_short dst_port" \ +"int alias_param" "int link_type" +.Bd -ragged -offset indent +This function adds new state to instance hash table. +Zero can be specified instead of dst_address and/or dst port. +This makes link partially specified dynamic. +However due to hashing method such links can be resolved on inbound (ext -> int) only. +.Ed +.Pp .Ft void .Fn LibAliasSetTarget "struct libalias *" "struct in_addr addr" .Bd -ragged -offset indent -- cgit v1.1 From 83fca1d193659201a31cad508665386117ffdd5d Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 22 Jun 2011 21:04:13 +0000 Subject: Move {amd64,i386}/pci/pci_bus.c and {amd64,i386}/include/pci_cfgreg.h to the x86 tree. The $PIR code is still only enabled on i386 and not amd64. While here, make the qpi(4) driver on conditional on 'device pci'. --- sys/amd64/include/pci_cfgreg.h | 44 +-- sys/amd64/pci/pci_bus.c | 435 ------------------------- sys/conf/files.amd64 | 4 +- sys/conf/files.i386 | 4 +- sys/conf/files.pc98 | 2 +- sys/i386/include/param.h | 1 + sys/i386/include/pci_cfgreg.h | 53 +-- sys/i386/pci/pci_bus.c | 700 --------------------------------------- sys/x86/include/pci_cfgreg.h | 60 ++++ sys/x86/pci/pci_bus.c | 719 +++++++++++++++++++++++++++++++++++++++++ 10 files changed, 791 insertions(+), 1231 deletions(-) delete mode 100644 sys/amd64/pci/pci_bus.c delete mode 100644 sys/i386/pci/pci_bus.c create mode 100644 sys/x86/include/pci_cfgreg.h create mode 100644 sys/x86/pci/pci_bus.c diff --git a/sys/amd64/include/pci_cfgreg.h b/sys/amd64/include/pci_cfgreg.h index 0358e79..717d5cc 100644 --- a/sys/amd64/include/pci_cfgreg.h +++ b/sys/amd64/include/pci_cfgreg.h @@ -1,44 +1,6 @@ /*- - * Copyright (c) 1997, Stefan Esser - * 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 unmodified, 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * $FreeBSD$ - * + * This file is in the public domain. */ +/* $FreeBSD$ */ -#define CONF1_ADDR_PORT 0x0cf8 -#define CONF1_DATA_PORT 0x0cfc - -#define CONF1_ENABLE 0x80000000ul -#define CONF1_ENABLE_CHK 0x80000000ul -#define CONF1_ENABLE_MSK 0x7f000000ul -#define CONF1_ENABLE_CHK1 0xff000001ul -#define CONF1_ENABLE_MSK1 0x80000001ul -#define CONF1_ENABLE_RES1 0x80000000ul - -u_long hostb_alloc_start(int type, u_long start, u_long end, u_long count); -int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus); -int pci_cfgregopen(void); -u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); -void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes); +#include diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c deleted file mode 100644 index 6d58575..0000000 --- a/sys/amd64/pci/pci_bus.c +++ /dev/null @@ -1,435 +0,0 @@ -/*- - * Copyright (c) 1997, Stefan Esser - * 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 unmodified, 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_cpu.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "pcib_if.h" - -int -legacy_pcib_maxslots(device_t dev) -{ - return 31; -} - -/* read configuration space register */ - -uint32_t -legacy_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, int bytes) -{ - return(pci_cfgregread(bus, slot, func, reg, bytes)); -} - -/* write configuration space register */ - -void -legacy_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, uint32_t data, int bytes) -{ - pci_cfgregwrite(bus, slot, func, reg, data, bytes); -} - -/* route interrupt */ - -static int -legacy_pcib_route_interrupt(device_t pcib, device_t dev, int pin) -{ - - /* No routing possible */ - return (PCI_INVALID_IRQ); -} - -/* Pass MSI requests up to the nexus. */ - -static int -legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, - int *irqs) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount, - irqs)); -} - -static int -legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); -} - -static int -legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, - uint32_t *data) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data)); -} - -static const char * -legacy_pcib_is_host_bridge(int bus, int slot, int func, - uint32_t id, uint8_t class, uint8_t subclass, - uint8_t *busnum) -{ - const char *s = NULL; - - *busnum = 0; - if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST) - s = "Host to PCI bridge"; - return s; -} - -/* - * Scan the first pci bus for host-pci bridges and add pcib instances - * to the nexus for each bridge. - */ -static void -legacy_pcib_identify(driver_t *driver, device_t parent) -{ - int bus, slot, func; - uint8_t hdrtype; - int found = 0; - int pcifunchigh; - int found824xx = 0; - int found_orion = 0; - device_t child; - devclass_t pci_devclass; - - if (pci_cfgregopen() == 0) - return; - /* - * Check to see if we haven't already had a PCI bus added - * via some other means. If we have, bail since otherwise - * we're going to end up duplicating it. - */ - if ((pci_devclass = devclass_find("pci")) && - devclass_get_device(pci_devclass, 0)) - return; - - - bus = 0; - retry: - for (slot = 0; slot <= PCI_SLOTMAX; slot++) { - func = 0; - hdrtype = legacy_pcib_read_config(0, bus, slot, func, - PCIR_HDRTYPE, 1); - /* - * When enumerating bus devices, the standard says that - * one should check the header type and ignore the slots whose - * header types that the software doesn't know about. We use - * this to filter out devices. - */ - if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) - continue; - if ((hdrtype & PCIM_MFDEV) && - (!found_orion || hdrtype != 0xff)) - pcifunchigh = PCI_FUNCMAX; - else - pcifunchigh = 0; - for (func = 0; func <= pcifunchigh; func++) { - /* - * Read the IDs and class from the device. - */ - uint32_t id; - uint8_t class, subclass, busnum; - const char *s; - device_t *devs; - int ndevs, i; - - id = legacy_pcib_read_config(0, bus, slot, func, - PCIR_DEVVENDOR, 4); - if (id == -1) - continue; - class = legacy_pcib_read_config(0, bus, slot, func, - PCIR_CLASS, 1); - subclass = legacy_pcib_read_config(0, bus, slot, func, - PCIR_SUBCLASS, 1); - - s = legacy_pcib_is_host_bridge(bus, slot, func, - id, class, subclass, - &busnum); - if (s == NULL) - continue; - - /* - * Check to see if the physical bus has already - * been seen. Eg: hybrid 32 and 64 bit host - * bridges to the same logical bus. - */ - if (device_get_children(parent, &devs, &ndevs) == 0) { - for (i = 0; s != NULL && i < ndevs; i++) { - if (strcmp(device_get_name(devs[i]), - "pcib") != 0) - continue; - if (legacy_get_pcibus(devs[i]) == busnum) - s = NULL; - } - free(devs, M_TEMP); - } - - if (s == NULL) - continue; - /* - * Add at priority 100 to make sure we - * go after any motherboard resources - */ - child = BUS_ADD_CHILD(parent, 100, - "pcib", busnum); - device_set_desc(child, s); - legacy_set_pcibus(child, busnum); - - found = 1; - if (id == 0x12258086) - found824xx = 1; - if (id == 0x84c48086) - found_orion = 1; - } - } - if (found824xx && bus == 0) { - bus++; - goto retry; - } - - /* - * Make sure we add at least one bridge since some old - * hardware doesn't actually have a host-pci bridge device. - * Note that pci_cfgregopen() thinks we have PCI devices.. - */ - if (!found) { - if (bootverbose) - printf( - "legacy_pcib_identify: no bridge found, adding pcib0 anyway\n"); - child = BUS_ADD_CHILD(parent, 100, "pcib", 0); - legacy_set_pcibus(child, 0); - } -} - -static int -legacy_pcib_probe(device_t dev) -{ - - if (pci_cfgregopen() == 0) - return ENXIO; - return -100; -} - -static int -legacy_pcib_attach(device_t dev) -{ - int bus; - - bus = pcib_get_bus(dev); - device_add_child(dev, "pci", bus); - return bus_generic_attach(dev); -} - -int -legacy_pcib_read_ivar(device_t dev, device_t child, int which, - uintptr_t *result) -{ - - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = 0; - return 0; - case PCIB_IVAR_BUS: - *result = legacy_get_pcibus(dev); - return 0; - } - return ENOENT; -} - -int -legacy_pcib_write_ivar(device_t dev, device_t child, int which, - uintptr_t value) -{ - - switch (which) { - case PCIB_IVAR_DOMAIN: - return EINVAL; - case PCIB_IVAR_BUS: - legacy_set_pcibus(dev, value); - return 0; - } - return ENOENT; -} - -/* - * Helper routine for x86 Host-PCI bridge driver resource allocation. - * This is used to adjust the start address of wildcard allocation - * requests to avoid low addresses that are known to be problematic. - * - * If no memory preference is given, use upper 32MB slot most BIOSes - * use for their memory window. This is typically only used on older - * laptops that don't have PCI busses behind a PCI bridge, so assuming - * > 32MB is likely OK. - * - * However, this can cause problems for other chipsets, so we make - * this tunable by hw.pci.host_mem_start. - */ -SYSCTL_DECL(_hw_pci); - -static unsigned long host_mem_start = 0x80000000; -TUNABLE_ULONG("hw.pci.host_mem_start", &host_mem_start); -SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start, - 0, "Limit the host bridge memory to being above this address."); - -u_long -hostb_alloc_start(int type, u_long start, u_long end, u_long count) -{ - - if (start + count - 1 != end) { - if (type == SYS_RES_MEMORY && start < host_mem_start) - start = host_mem_start; - if (type == SYS_RES_IOPORT && start < 0x1000) - start = 0x1000; - } - return (start); -} - -struct resource * -legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - - start = hostb_alloc_start(type, start, end, count); - return (bus_generic_alloc_resource(dev, child, type, rid, start, end, - count, flags)); -} - -static device_method_t legacy_pcib_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, legacy_pcib_identify), - DEVMETHOD(device_probe, legacy_pcib_probe), - DEVMETHOD(device_attach, legacy_pcib_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar), - DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar), - DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource), - DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - /* pcib interface */ - DEVMETHOD(pcib_maxslots, legacy_pcib_maxslots), - DEVMETHOD(pcib_read_config, legacy_pcib_read_config), - DEVMETHOD(pcib_write_config, legacy_pcib_write_config), - DEVMETHOD(pcib_route_interrupt, legacy_pcib_route_interrupt), - DEVMETHOD(pcib_alloc_msi, legacy_pcib_alloc_msi), - DEVMETHOD(pcib_release_msi, pcib_release_msi), - DEVMETHOD(pcib_alloc_msix, legacy_pcib_alloc_msix), - DEVMETHOD(pcib_release_msix, pcib_release_msix), - DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi), - - { 0, 0 } -}; - -static devclass_t hostb_devclass; - -DEFINE_CLASS_0(pcib, legacy_pcib_driver, legacy_pcib_methods, 1); -DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, hostb_devclass, 0, 0); - - -/* - * Install placeholder to claim the resources owned by the - * PCI bus interface. This could be used to extract the - * config space registers in the extreme case where the PnP - * ID is available and the PCI BIOS isn't, but for now we just - * eat the PnP ID and do nothing else. - * - * XXX we should silence this probe, as it will generally confuse - * people. - */ -static struct isa_pnp_id pcibus_pnp_ids[] = { - { 0x030ad041 /* PNP0A03 */, "PCI Bus" }, - { 0x080ad041 /* PNP0A08 */, "PCIe Bus" }, - { 0 } -}; - -static int -pcibus_pnp_probe(device_t dev) -{ - int result; - - if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0) - device_quiet(dev); - return(result); -} - -static int -pcibus_pnp_attach(device_t dev) -{ - return(0); -} - -static device_method_t pcibus_pnp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pcibus_pnp_probe), - DEVMETHOD(device_attach, pcibus_pnp_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - { 0, 0 } -}; - -static devclass_t pcibus_pnp_devclass; - -DEFINE_CLASS_0(pcibus_pnp, pcibus_pnp_driver, pcibus_pnp_methods, 1); -DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0); diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 7916845..1388d01 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -128,7 +128,6 @@ amd64/amd64/trap.c standard amd64/amd64/uio_machdep.c standard amd64/amd64/uma_machdep.c standard amd64/amd64/vm_machdep.c standard -amd64/pci/pci_bus.c optional pci amd64/pci/pci_cfgreg.c optional pci crypto/aesni/aesencdec_amd64.S optional aesni crypto/aesni/aeskeys_amd64.S optional aesni @@ -315,7 +314,8 @@ x86/isa/isa.c standard x86/isa/isa_dma.c standard x86/isa/nmi.c standard x86/isa/orm.c optional isa -x86/pci/qpi.c standard +x86/pci/pci_bus.c optional pci +x86/pci/qpi.c optional pci x86/x86/busdma_machdep.c standard x86/x86/dump_machdep.c standard x86/x86/io_apic.c standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 4f0d0d0..41a1772 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -352,7 +352,6 @@ i386/linux/linux_support.s optional compat_linux \ dependency "linux_assym.h" i386/linux/linux_sysent.c optional compat_linux i386/linux/linux_sysvec.c optional compat_linux -i386/pci/pci_bus.c optional pci i386/pci/pci_cfgreg.c optional pci i386/pci/pci_pir.c optional pci i386/svr4/svr4_locore.s optional compat_svr4 \ @@ -405,7 +404,8 @@ x86/isa/isa.c optional isa x86/isa/isa_dma.c optional isa x86/isa/nmi.c standard x86/isa/orm.c optional isa -x86/pci/qpi.c standard +x86/pci/pci_bus.c optional pci +x86/pci/qpi.c optional pci x86/x86/busdma_machdep.c standard x86/x86/dump_machdep.c standard x86/x86/io_apic.c optional apic diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index 5db5421..e034601 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -199,7 +199,6 @@ i386/linux/linux_support.s optional compat_linux \ dependency "linux_assym.h" i386/linux/linux_sysent.c optional compat_linux i386/linux/linux_sysvec.c optional compat_linux -i386/pci/pci_bus.c optional pci i386/pci/pci_cfgreg.c optional pci i386/pci/pci_pir.c optional pci i386/svr4/svr4_locore.s optional compat_svr4 \ @@ -249,6 +248,7 @@ pc98/pc98/pc98_machdep.c standard x86/isa/atpic.c optional atpic x86/isa/clock.c standard x86/isa/isa.c optional isa +x86/pci/pci_bus.c optional pci x86/x86/busdma_machdep.c standard x86/x86/dump_machdep.c standard x86/x86/io_apic.c optional apic diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h index 11ac12e..d95fcf3 100644 --- a/sys/i386/include/param.h +++ b/sys/i386/include/param.h @@ -56,6 +56,7 @@ #define __HAVE_ACPI +#define __HAVE_PIR #define __PCI_REROUTE_INTERRUPT #ifndef MACHINE diff --git a/sys/i386/include/pci_cfgreg.h b/sys/i386/include/pci_cfgreg.h index 6995971..717d5cc 100644 --- a/sys/i386/include/pci_cfgreg.h +++ b/sys/i386/include/pci_cfgreg.h @@ -1,53 +1,6 @@ /*- - * Copyright (c) 1997, Stefan Esser - * 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 unmodified, 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - * $FreeBSD$ - * + * This file is in the public domain. */ +/* $FreeBSD$ */ -#define CONF1_ADDR_PORT 0x0cf8 -#define CONF1_DATA_PORT 0x0cfc - -#define CONF1_ENABLE 0x80000000ul -#define CONF1_ENABLE_CHK 0x80000000ul -#define CONF1_ENABLE_MSK 0x7f000000ul -#define CONF1_ENABLE_CHK1 0xff000001ul -#define CONF1_ENABLE_MSK1 0x80000001ul -#define CONF1_ENABLE_RES1 0x80000000ul - -#define CONF2_ENABLE_PORT 0x0cf8 -#define CONF2_FORWARD_PORT 0x0cfa - -#define CONF2_ENABLE_CHK 0x0e -#define CONF2_ENABLE_RES 0x0e - -u_long hostb_alloc_start(int type, u_long start, u_long end, u_long count); -int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus); -int pci_cfgregopen(void); -u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); -void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes); -void pci_pir_open(void); -int pci_pir_probe(int bus, int require_parse); -int pci_pir_route_interrupt(int bus, int device, int func, int pin); +#include diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c deleted file mode 100644 index c247180..0000000 --- a/sys/i386/pci/pci_bus.c +++ /dev/null @@ -1,700 +0,0 @@ -/*- - * Copyright (c) 1997, Stefan Esser - * 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 unmodified, 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_cpu.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#ifdef CPU_ELAN -#include -#endif -#include -#include -#include - -#include "pcib_if.h" - -static int pcibios_pcib_route_interrupt(device_t pcib, device_t dev, - int pin); - -int -legacy_pcib_maxslots(device_t dev) -{ - return 31; -} - -/* read configuration space register */ - -uint32_t -legacy_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, int bytes) -{ - return(pci_cfgregread(bus, slot, func, reg, bytes)); -} - -/* write configuration space register */ - -void -legacy_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, - u_int reg, uint32_t data, int bytes) -{ - pci_cfgregwrite(bus, slot, func, reg, data, bytes); -} - -/* Pass MSI requests up to the nexus. */ - -static int -legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, - int *irqs) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount, - irqs)); -} - -static int -legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); -} - -static int -legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, - uint32_t *data) -{ - device_t bus; - - bus = device_get_parent(pcib); - return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data)); -} - -static const char * -legacy_pcib_is_host_bridge(int bus, int slot, int func, - uint32_t id, uint8_t class, uint8_t subclass, - uint8_t *busnum) -{ - const char *s = NULL; - static uint8_t pxb[4]; /* hack for 450nx */ - - *busnum = 0; - - switch (id) { - case 0x12258086: - s = "Intel 824?? host to PCI bridge"; - /* XXX This is a guess */ - /* *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x41, 1); */ - *busnum = bus; - break; - case 0x71208086: - s = "Intel 82810 (i810 GMCH) Host To Hub bridge"; - break; - case 0x71228086: - s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge"; - break; - case 0x71248086: - s = "Intel 82810E (i810E GMCH) Host To Hub bridge"; - break; - case 0x11308086: - s = "Intel 82815 (i815 GMCH) Host To Hub bridge"; - break; - case 0x71808086: - s = "Intel 82443LX (440 LX) host to PCI bridge"; - break; - case 0x71908086: - s = "Intel 82443BX (440 BX) host to PCI bridge"; - break; - case 0x71928086: - s = "Intel 82443BX host to PCI bridge (AGP disabled)"; - break; - case 0x71948086: - s = "Intel 82443MX host to PCI bridge"; - break; - case 0x71a08086: - s = "Intel 82443GX host to PCI bridge"; - break; - case 0x71a18086: - s = "Intel 82443GX host to AGP bridge"; - break; - case 0x71a28086: - s = "Intel 82443GX host to PCI bridge (AGP disabled)"; - break; - case 0x84c48086: - s = "Intel 82454KX/GX (Orion) host to PCI bridge"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x4a, 1); - break; - case 0x84ca8086: - /* - * For the 450nx chipset, there is a whole bundle of - * things pretending to be host bridges. The MIOC will - * be seen first and isn't really a pci bridge (the - * actual busses are attached to the PXB's). We need to - * read the registers of the MIOC to figure out the - * bus numbers for the PXB channels. - * - * Since the MIOC doesn't have a pci bus attached, we - * pretend it wasn't there. - */ - pxb[0] = legacy_pcib_read_config(0, bus, slot, func, - 0xd0, 1); /* BUSNO[0] */ - pxb[1] = legacy_pcib_read_config(0, bus, slot, func, - 0xd1, 1) + 1; /* SUBA[0]+1 */ - pxb[2] = legacy_pcib_read_config(0, bus, slot, func, - 0xd3, 1); /* BUSNO[1] */ - pxb[3] = legacy_pcib_read_config(0, bus, slot, func, - 0xd4, 1) + 1; /* SUBA[1]+1 */ - return NULL; - case 0x84cb8086: - switch (slot) { - case 0x12: - s = "Intel 82454NX PXB#0, Bus#A"; - *busnum = pxb[0]; - break; - case 0x13: - s = "Intel 82454NX PXB#0, Bus#B"; - *busnum = pxb[1]; - break; - case 0x14: - s = "Intel 82454NX PXB#1, Bus#A"; - *busnum = pxb[2]; - break; - case 0x15: - s = "Intel 82454NX PXB#1, Bus#B"; - *busnum = pxb[3]; - break; - } - break; - case 0x1A308086: - s = "Intel 82845 Host to PCI bridge"; - break; - - /* AMD -- vendor 0x1022 */ - case 0x30001022: - s = "AMD Elan SC520 host to PCI bridge"; -#ifdef CPU_ELAN - init_AMD_Elan_sc520(); -#else - printf( -"*** WARNING: missing CPU_ELAN -- timekeeping may be wrong\n"); -#endif - break; - case 0x70061022: - s = "AMD-751 host to PCI bridge"; - break; - case 0x700e1022: - s = "AMD-761 host to PCI bridge"; - break; - - /* SiS -- vendor 0x1039 */ - case 0x04961039: - s = "SiS 85c496"; - break; - case 0x04061039: - s = "SiS 85c501"; - break; - case 0x06011039: - s = "SiS 85c601"; - break; - case 0x55911039: - s = "SiS 5591 host to PCI bridge"; - break; - case 0x00011039: - s = "SiS 5591 host to AGP bridge"; - break; - - /* VLSI -- vendor 0x1004 */ - case 0x00051004: - s = "VLSI 82C592 Host to PCI bridge"; - break; - - /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */ - /* totally. Please let me know if anything wrong. -F */ - /* XXX need info on the MVP3 -- any takers? */ - case 0x05981106: - s = "VIA 82C598MVP (Apollo MVP3) host bridge"; - break; - - /* AcerLabs -- vendor 0x10b9 */ - /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ - /* id is '10b9" but the register always shows "10b9". -Foxfair */ - case 0x154110b9: - s = "AcerLabs M1541 (Aladdin-V) PCI host bridge"; - break; - - /* OPTi -- vendor 0x1045 */ - case 0xc7011045: - s = "OPTi 82C700 host to PCI bridge"; - break; - case 0xc8221045: - s = "OPTi 82C822 host to PCI Bridge"; - break; - - /* ServerWorks -- vendor 0x1166 */ - case 0x00051166: - s = "ServerWorks NB6536 2.0HE host to PCI bridge"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); - break; - - case 0x00061166: - /* FALLTHROUGH */ - case 0x00081166: - /* FALLTHROUGH */ - case 0x02011166: - /* FALLTHROUGH */ - case 0x010f1014: /* IBM re-badged ServerWorks chipset */ - s = "ServerWorks host to PCI bridge"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); - break; - - case 0x00091166: - s = "ServerWorks NB6635 3.0LE host to PCI bridge"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); - break; - - case 0x00101166: - s = "ServerWorks CIOB30 host to PCI bridge"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); - break; - - case 0x00111166: - /* FALLTHROUGH */ - case 0x03021014: /* IBM re-badged ServerWorks chipset */ - s = "ServerWorks CMIC-HE host to PCI-X bridge"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); - break; - - /* XXX unknown chipset, but working */ - case 0x00171166: - /* FALLTHROUGH */ - case 0x01011166: - case 0x01101166: - case 0x02251166: - s = "ServerWorks host to PCI bridge(unknown chipset)"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); - break; - - /* Compaq/HP -- vendor 0x0e11 */ - case 0x60100e11: - s = "Compaq/HP Model 6010 HotPlug PCI Bridge"; - *busnum = legacy_pcib_read_config(0, bus, slot, func, 0xc8, 1); - break; - - /* Integrated Micro Solutions -- vendor 0x10e0 */ - case 0x884910e0: - s = "Integrated Micro Solutions VL Bridge"; - break; - - default: - if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST) - s = "Host to PCI bridge"; - break; - } - - return s; -} - -/* - * Scan the first pci bus for host-pci bridges and add pcib instances - * to the nexus for each bridge. - */ -static void -legacy_pcib_identify(driver_t *driver, device_t parent) -{ - int bus, slot, func; - uint8_t hdrtype; - int found = 0; - int pcifunchigh; - int found824xx = 0; - int found_orion = 0; - device_t child; - devclass_t pci_devclass; - - if (pci_cfgregopen() == 0) - return; - /* - * Check to see if we haven't already had a PCI bus added - * via some other means. If we have, bail since otherwise - * we're going to end up duplicating it. - */ - if ((pci_devclass = devclass_find("pci")) && - devclass_get_device(pci_devclass, 0)) - return; - - - bus = 0; - retry: - for (slot = 0; slot <= PCI_SLOTMAX; slot++) { - func = 0; - hdrtype = legacy_pcib_read_config(0, bus, slot, func, - PCIR_HDRTYPE, 1); - /* - * When enumerating bus devices, the standard says that - * one should check the header type and ignore the slots whose - * header types that the software doesn't know about. We use - * this to filter out devices. - */ - if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) - continue; - if ((hdrtype & PCIM_MFDEV) && - (!found_orion || hdrtype != 0xff)) - pcifunchigh = PCI_FUNCMAX; - else - pcifunchigh = 0; - for (func = 0; func <= pcifunchigh; func++) { - /* - * Read the IDs and class from the device. - */ - uint32_t id; - uint8_t class, subclass, busnum; - const char *s; - device_t *devs; - int ndevs, i; - - id = legacy_pcib_read_config(0, bus, slot, func, - PCIR_DEVVENDOR, 4); - if (id == -1) - continue; - class = legacy_pcib_read_config(0, bus, slot, func, - PCIR_CLASS, 1); - subclass = legacy_pcib_read_config(0, bus, slot, func, - PCIR_SUBCLASS, 1); - - s = legacy_pcib_is_host_bridge(bus, slot, func, - id, class, subclass, - &busnum); - if (s == NULL) - continue; - - /* - * Check to see if the physical bus has already - * been seen. Eg: hybrid 32 and 64 bit host - * bridges to the same logical bus. - */ - if (device_get_children(parent, &devs, &ndevs) == 0) { - for (i = 0; s != NULL && i < ndevs; i++) { - if (strcmp(device_get_name(devs[i]), - "pcib") != 0) - continue; - if (legacy_get_pcibus(devs[i]) == busnum) - s = NULL; - } - free(devs, M_TEMP); - } - - if (s == NULL) - continue; - /* - * Add at priority 100 to make sure we - * go after any motherboard resources - */ - child = BUS_ADD_CHILD(parent, 100, - "pcib", busnum); - device_set_desc(child, s); - legacy_set_pcibus(child, busnum); - - found = 1; - if (id == 0x12258086) - found824xx = 1; - if (id == 0x84c48086) - found_orion = 1; - } - } - if (found824xx && bus == 0) { - bus++; - goto retry; - } - - /* - * Make sure we add at least one bridge since some old - * hardware doesn't actually have a host-pci bridge device. - * Note that pci_cfgregopen() thinks we have PCI devices.. - */ - if (!found) { - if (bootverbose) - printf( - "legacy_pcib_identify: no bridge found, adding pcib0 anyway\n"); - child = BUS_ADD_CHILD(parent, 100, "pcib", 0); - legacy_set_pcibus(child, 0); - } -} - -static int -legacy_pcib_probe(device_t dev) -{ - - if (pci_cfgregopen() == 0) - return ENXIO; - return -100; -} - -static int -legacy_pcib_attach(device_t dev) -{ - device_t pir; - int bus; - - /* - * Look for a PCI BIOS interrupt routing table as that will be - * our method of routing interrupts if we have one. - */ - bus = pcib_get_bus(dev); - if (pci_pir_probe(bus, 0)) { - pir = BUS_ADD_CHILD(device_get_parent(dev), 0, "pir", 0); - if (pir != NULL) - device_probe_and_attach(pir); - } - device_add_child(dev, "pci", bus); - return bus_generic_attach(dev); -} - -int -legacy_pcib_read_ivar(device_t dev, device_t child, int which, - uintptr_t *result) -{ - - switch (which) { - case PCIB_IVAR_DOMAIN: - *result = 0; - return 0; - case PCIB_IVAR_BUS: - *result = legacy_get_pcibus(dev); - return 0; - } - return ENOENT; -} - -int -legacy_pcib_write_ivar(device_t dev, device_t child, int which, - uintptr_t value) -{ - - switch (which) { - case PCIB_IVAR_DOMAIN: - return EINVAL; - case PCIB_IVAR_BUS: - legacy_set_pcibus(dev, value); - return 0; - } - return ENOENT; -} - -/* - * Helper routine for x86 Host-PCI bridge driver resource allocation. - * This is used to adjust the start address of wildcard allocation - * requests to avoid low addresses that are known to be problematic. - * - * If no memory preference is given, use upper 32MB slot most BIOSes - * use for their memory window. This is typically only used on older - * laptops that don't have PCI busses behind a PCI bridge, so assuming - * > 32MB is likely OK. - * - * However, this can cause problems for other chipsets, so we make - * this tunable by hw.pci.host_mem_start. - */ -SYSCTL_DECL(_hw_pci); - -static unsigned long host_mem_start = 0x80000000; -TUNABLE_ULONG("hw.pci.host_mem_start", &host_mem_start); -SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start, - 0, "Limit the host bridge memory to being above this address."); - -u_long -hostb_alloc_start(int type, u_long start, u_long end, u_long count) -{ - - if (start + count - 1 != end) { - if (type == SYS_RES_MEMORY && start < host_mem_start) - start = host_mem_start; - if (type == SYS_RES_IOPORT && start < 0x1000) - start = 0x1000; - } - return (start); -} - -struct resource * -legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - - start = hostb_alloc_start(type, start, end, count); - return (bus_generic_alloc_resource(dev, child, type, rid, start, end, - count, flags)); -} - -static device_method_t legacy_pcib_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, legacy_pcib_identify), - DEVMETHOD(device_probe, legacy_pcib_probe), - DEVMETHOD(device_attach, legacy_pcib_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar), - DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar), - DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource), - DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - /* pcib interface */ - DEVMETHOD(pcib_maxslots, legacy_pcib_maxslots), - DEVMETHOD(pcib_read_config, legacy_pcib_read_config), - DEVMETHOD(pcib_write_config, legacy_pcib_write_config), - DEVMETHOD(pcib_route_interrupt, pcibios_pcib_route_interrupt), - DEVMETHOD(pcib_alloc_msi, legacy_pcib_alloc_msi), - DEVMETHOD(pcib_release_msi, pcib_release_msi), - DEVMETHOD(pcib_alloc_msix, legacy_pcib_alloc_msix), - DEVMETHOD(pcib_release_msix, pcib_release_msix), - DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi), - - { 0, 0 } -}; - -static devclass_t hostb_devclass; - -DEFINE_CLASS_0(pcib, legacy_pcib_driver, legacy_pcib_methods, 1); -DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, hostb_devclass, 0, 0); - - -/* - * Install placeholder to claim the resources owned by the - * PCI bus interface. This could be used to extract the - * config space registers in the extreme case where the PnP - * ID is available and the PCI BIOS isn't, but for now we just - * eat the PnP ID and do nothing else. - * - * XXX we should silence this probe, as it will generally confuse - * people. - */ -static struct isa_pnp_id pcibus_pnp_ids[] = { - { 0x030ad041 /* PNP0A03 */, "PCI Bus" }, - { 0x080ad041 /* PNP0A08 */, "PCIe Bus" }, - { 0 } -}; - -static int -pcibus_pnp_probe(device_t dev) -{ - int result; - - if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0) - device_quiet(dev); - return(result); -} - -static int -pcibus_pnp_attach(device_t dev) -{ - return(0); -} - -static device_method_t pcibus_pnp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pcibus_pnp_probe), - DEVMETHOD(device_attach, pcibus_pnp_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - { 0, 0 } -}; - -static devclass_t pcibus_pnp_devclass; - -DEFINE_CLASS_0(pcibus_pnp, pcibus_pnp_driver, pcibus_pnp_methods, 1); -DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0); - - -/* - * Provide a PCI-PCI bridge driver for PCI busses behind PCI-PCI bridges - * that appear in the PCIBIOS Interrupt Routing Table to use the routing - * table for interrupt routing when possible. - */ -static int pcibios_pcib_probe(device_t bus); - -static device_method_t pcibios_pcib_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pcibios_pcib_probe), - - /* pcib interface */ - DEVMETHOD(pcib_route_interrupt, pcibios_pcib_route_interrupt), - - {0, 0} -}; - -static devclass_t pcib_devclass; - -DEFINE_CLASS_1(pcib, pcibios_pcib_driver, pcibios_pcib_pci_methods, - sizeof(struct pcib_softc), pcib_driver); -DRIVER_MODULE(pcibios_pcib, pci, pcibios_pcib_driver, pcib_devclass, 0, 0); - -static int -pcibios_pcib_probe(device_t dev) -{ - int bus; - - if ((pci_get_class(dev) != PCIC_BRIDGE) || - (pci_get_subclass(dev) != PCIS_BRIDGE_PCI)) - return (ENXIO); - bus = pci_read_config(dev, PCIR_SECBUS_1, 1); - if (bus == 0) - return (ENXIO); - if (!pci_pir_probe(bus, 1)) - return (ENXIO); - device_set_desc(dev, "PCIBIOS PCI-PCI bridge"); - return (-2000); -} - -static int -pcibios_pcib_route_interrupt(device_t pcib, device_t dev, int pin) -{ - return (pci_pir_route_interrupt(pci_get_bus(dev), pci_get_slot(dev), - pci_get_function(dev), pin)); -} diff --git a/sys/x86/include/pci_cfgreg.h b/sys/x86/include/pci_cfgreg.h new file mode 100644 index 0000000..ea5e319 --- /dev/null +++ b/sys/x86/include/pci_cfgreg.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 1997, Stefan Esser + * 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 unmodified, 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + * + */ + +#ifndef __X86_PCI_CFGREG_H__ +#define __X86_PCI_CFGREG_H__ + +#define CONF1_ADDR_PORT 0x0cf8 +#define CONF1_DATA_PORT 0x0cfc + +#define CONF1_ENABLE 0x80000000ul +#define CONF1_ENABLE_CHK 0x80000000ul +#define CONF1_ENABLE_MSK 0x7f000000ul +#define CONF1_ENABLE_CHK1 0xff000001ul +#define CONF1_ENABLE_MSK1 0x80000001ul +#define CONF1_ENABLE_RES1 0x80000000ul + +#define CONF2_ENABLE_PORT 0x0cf8 +#define CONF2_FORWARD_PORT 0x0cfa + +#define CONF2_ENABLE_CHK 0x0e +#define CONF2_ENABLE_RES 0x0e + +u_long hostb_alloc_start(int type, u_long start, u_long end, u_long count); +int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus); +int pci_cfgregopen(void); +u_int32_t pci_cfgregread(int bus, int slot, int func, int reg, int bytes); +void pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes); +#ifdef __HAVE_PIR +void pci_pir_open(void); +int pci_pir_probe(int bus, int require_parse); +int pci_pir_route_interrupt(int bus, int device, int func, int pin); +#endif + +#endif /* !__X86_PCI_CFGREG_H__ */ diff --git a/sys/x86/pci/pci_bus.c b/sys/x86/pci/pci_bus.c new file mode 100644 index 0000000..0efac6e --- /dev/null +++ b/sys/x86/pci/pci_bus.c @@ -0,0 +1,719 @@ +/*- + * Copyright (c) 1997, Stefan Esser + * 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 unmodified, 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_cpu.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifdef CPU_ELAN +#include +#endif +#include +#include +#include + +#include "pcib_if.h" + +int +legacy_pcib_maxslots(device_t dev) +{ + return 31; +} + +/* read configuration space register */ + +uint32_t +legacy_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, int bytes) +{ + return(pci_cfgregread(bus, slot, func, reg, bytes)); +} + +/* write configuration space register */ + +void +legacy_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, uint32_t data, int bytes) +{ + pci_cfgregwrite(bus, slot, func, reg, data, bytes); +} + +/* route interrupt */ + +static int +legacy_pcib_route_interrupt(device_t pcib, device_t dev, int pin) +{ + +#ifdef __HAVE_PIR + return (pci_pir_route_interrupt(pci_get_bus(dev), pci_get_slot(dev), + pci_get_function(dev), pin)); +#else + /* No routing possible */ + return (PCI_INVALID_IRQ); +#endif +} + +/* Pass MSI requests up to the nexus. */ + +static int +legacy_pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, + int *irqs) +{ + device_t bus; + + bus = device_get_parent(pcib); + return (PCIB_ALLOC_MSI(device_get_parent(bus), dev, count, maxcount, + irqs)); +} + +static int +legacy_pcib_alloc_msix(device_t pcib, device_t dev, int *irq) +{ + device_t bus; + + bus = device_get_parent(pcib); + return (PCIB_ALLOC_MSIX(device_get_parent(bus), dev, irq)); +} + +static int +legacy_pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, + uint32_t *data) +{ + device_t bus; + + bus = device_get_parent(pcib); + return (PCIB_MAP_MSI(device_get_parent(bus), dev, irq, addr, data)); +} + +static const char * +legacy_pcib_is_host_bridge(int bus, int slot, int func, + uint32_t id, uint8_t class, uint8_t subclass, + uint8_t *busnum) +{ +#ifdef __i386__ + const char *s = NULL; + static uint8_t pxb[4]; /* hack for 450nx */ + + *busnum = 0; + + switch (id) { + case 0x12258086: + s = "Intel 824?? host to PCI bridge"; + /* XXX This is a guess */ + /* *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x41, 1); */ + *busnum = bus; + break; + case 0x71208086: + s = "Intel 82810 (i810 GMCH) Host To Hub bridge"; + break; + case 0x71228086: + s = "Intel 82810-DC100 (i810-DC100 GMCH) Host To Hub bridge"; + break; + case 0x71248086: + s = "Intel 82810E (i810E GMCH) Host To Hub bridge"; + break; + case 0x11308086: + s = "Intel 82815 (i815 GMCH) Host To Hub bridge"; + break; + case 0x71808086: + s = "Intel 82443LX (440 LX) host to PCI bridge"; + break; + case 0x71908086: + s = "Intel 82443BX (440 BX) host to PCI bridge"; + break; + case 0x71928086: + s = "Intel 82443BX host to PCI bridge (AGP disabled)"; + break; + case 0x71948086: + s = "Intel 82443MX host to PCI bridge"; + break; + case 0x71a08086: + s = "Intel 82443GX host to PCI bridge"; + break; + case 0x71a18086: + s = "Intel 82443GX host to AGP bridge"; + break; + case 0x71a28086: + s = "Intel 82443GX host to PCI bridge (AGP disabled)"; + break; + case 0x84c48086: + s = "Intel 82454KX/GX (Orion) host to PCI bridge"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x4a, 1); + break; + case 0x84ca8086: + /* + * For the 450nx chipset, there is a whole bundle of + * things pretending to be host bridges. The MIOC will + * be seen first and isn't really a pci bridge (the + * actual busses are attached to the PXB's). We need to + * read the registers of the MIOC to figure out the + * bus numbers for the PXB channels. + * + * Since the MIOC doesn't have a pci bus attached, we + * pretend it wasn't there. + */ + pxb[0] = legacy_pcib_read_config(0, bus, slot, func, + 0xd0, 1); /* BUSNO[0] */ + pxb[1] = legacy_pcib_read_config(0, bus, slot, func, + 0xd1, 1) + 1; /* SUBA[0]+1 */ + pxb[2] = legacy_pcib_read_config(0, bus, slot, func, + 0xd3, 1); /* BUSNO[1] */ + pxb[3] = legacy_pcib_read_config(0, bus, slot, func, + 0xd4, 1) + 1; /* SUBA[1]+1 */ + return NULL; + case 0x84cb8086: + switch (slot) { + case 0x12: + s = "Intel 82454NX PXB#0, Bus#A"; + *busnum = pxb[0]; + break; + case 0x13: + s = "Intel 82454NX PXB#0, Bus#B"; + *busnum = pxb[1]; + break; + case 0x14: + s = "Intel 82454NX PXB#1, Bus#A"; + *busnum = pxb[2]; + break; + case 0x15: + s = "Intel 82454NX PXB#1, Bus#B"; + *busnum = pxb[3]; + break; + } + break; + case 0x1A308086: + s = "Intel 82845 Host to PCI bridge"; + break; + + /* AMD -- vendor 0x1022 */ + case 0x30001022: + s = "AMD Elan SC520 host to PCI bridge"; +#ifdef CPU_ELAN + init_AMD_Elan_sc520(); +#else + printf( +"*** WARNING: missing CPU_ELAN -- timekeeping may be wrong\n"); +#endif + break; + case 0x70061022: + s = "AMD-751 host to PCI bridge"; + break; + case 0x700e1022: + s = "AMD-761 host to PCI bridge"; + break; + + /* SiS -- vendor 0x1039 */ + case 0x04961039: + s = "SiS 85c496"; + break; + case 0x04061039: + s = "SiS 85c501"; + break; + case 0x06011039: + s = "SiS 85c601"; + break; + case 0x55911039: + s = "SiS 5591 host to PCI bridge"; + break; + case 0x00011039: + s = "SiS 5591 host to AGP bridge"; + break; + + /* VLSI -- vendor 0x1004 */ + case 0x00051004: + s = "VLSI 82C592 Host to PCI bridge"; + break; + + /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */ + /* totally. Please let me know if anything wrong. -F */ + /* XXX need info on the MVP3 -- any takers? */ + case 0x05981106: + s = "VIA 82C598MVP (Apollo MVP3) host bridge"; + break; + + /* AcerLabs -- vendor 0x10b9 */ + /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ + /* id is '10b9" but the register always shows "10b9". -Foxfair */ + case 0x154110b9: + s = "AcerLabs M1541 (Aladdin-V) PCI host bridge"; + break; + + /* OPTi -- vendor 0x1045 */ + case 0xc7011045: + s = "OPTi 82C700 host to PCI bridge"; + break; + case 0xc8221045: + s = "OPTi 82C822 host to PCI Bridge"; + break; + + /* ServerWorks -- vendor 0x1166 */ + case 0x00051166: + s = "ServerWorks NB6536 2.0HE host to PCI bridge"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); + break; + + case 0x00061166: + /* FALLTHROUGH */ + case 0x00081166: + /* FALLTHROUGH */ + case 0x02011166: + /* FALLTHROUGH */ + case 0x010f1014: /* IBM re-badged ServerWorks chipset */ + s = "ServerWorks host to PCI bridge"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); + break; + + case 0x00091166: + s = "ServerWorks NB6635 3.0LE host to PCI bridge"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); + break; + + case 0x00101166: + s = "ServerWorks CIOB30 host to PCI bridge"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); + break; + + case 0x00111166: + /* FALLTHROUGH */ + case 0x03021014: /* IBM re-badged ServerWorks chipset */ + s = "ServerWorks CMIC-HE host to PCI-X bridge"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); + break; + + /* XXX unknown chipset, but working */ + case 0x00171166: + /* FALLTHROUGH */ + case 0x01011166: + case 0x01101166: + case 0x02251166: + s = "ServerWorks host to PCI bridge(unknown chipset)"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0x44, 1); + break; + + /* Compaq/HP -- vendor 0x0e11 */ + case 0x60100e11: + s = "Compaq/HP Model 6010 HotPlug PCI Bridge"; + *busnum = legacy_pcib_read_config(0, bus, slot, func, 0xc8, 1); + break; + + /* Integrated Micro Solutions -- vendor 0x10e0 */ + case 0x884910e0: + s = "Integrated Micro Solutions VL Bridge"; + break; + + default: + if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST) + s = "Host to PCI bridge"; + break; + } + + return s; +#else + const char *s = NULL; + + *busnum = 0; + if (class == PCIC_BRIDGE && subclass == PCIS_BRIDGE_HOST) + s = "Host to PCI bridge"; + return s; +#endif +} + +/* + * Scan the first pci bus for host-pci bridges and add pcib instances + * to the nexus for each bridge. + */ +static void +legacy_pcib_identify(driver_t *driver, device_t parent) +{ + int bus, slot, func; + uint8_t hdrtype; + int found = 0; + int pcifunchigh; + int found824xx = 0; + int found_orion = 0; + device_t child; + devclass_t pci_devclass; + + if (pci_cfgregopen() == 0) + return; + /* + * Check to see if we haven't already had a PCI bus added + * via some other means. If we have, bail since otherwise + * we're going to end up duplicating it. + */ + if ((pci_devclass = devclass_find("pci")) && + devclass_get_device(pci_devclass, 0)) + return; + + + bus = 0; + retry: + for (slot = 0; slot <= PCI_SLOTMAX; slot++) { + func = 0; + hdrtype = legacy_pcib_read_config(0, bus, slot, func, + PCIR_HDRTYPE, 1); + /* + * When enumerating bus devices, the standard says that + * one should check the header type and ignore the slots whose + * header types that the software doesn't know about. We use + * this to filter out devices. + */ + if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) + continue; + if ((hdrtype & PCIM_MFDEV) && + (!found_orion || hdrtype != 0xff)) + pcifunchigh = PCI_FUNCMAX; + else + pcifunchigh = 0; + for (func = 0; func <= pcifunchigh; func++) { + /* + * Read the IDs and class from the device. + */ + uint32_t id; + uint8_t class, subclass, busnum; + const char *s; + device_t *devs; + int ndevs, i; + + id = legacy_pcib_read_config(0, bus, slot, func, + PCIR_DEVVENDOR, 4); + if (id == -1) + continue; + class = legacy_pcib_read_config(0, bus, slot, func, + PCIR_CLASS, 1); + subclass = legacy_pcib_read_config(0, bus, slot, func, + PCIR_SUBCLASS, 1); + + s = legacy_pcib_is_host_bridge(bus, slot, func, + id, class, subclass, + &busnum); + if (s == NULL) + continue; + + /* + * Check to see if the physical bus has already + * been seen. Eg: hybrid 32 and 64 bit host + * bridges to the same logical bus. + */ + if (device_get_children(parent, &devs, &ndevs) == 0) { + for (i = 0; s != NULL && i < ndevs; i++) { + if (strcmp(device_get_name(devs[i]), + "pcib") != 0) + continue; + if (legacy_get_pcibus(devs[i]) == busnum) + s = NULL; + } + free(devs, M_TEMP); + } + + if (s == NULL) + continue; + /* + * Add at priority 100 to make sure we + * go after any motherboard resources + */ + child = BUS_ADD_CHILD(parent, 100, + "pcib", busnum); + device_set_desc(child, s); + legacy_set_pcibus(child, busnum); + + found = 1; + if (id == 0x12258086) + found824xx = 1; + if (id == 0x84c48086) + found_orion = 1; + } + } + if (found824xx && bus == 0) { + bus++; + goto retry; + } + + /* + * Make sure we add at least one bridge since some old + * hardware doesn't actually have a host-pci bridge device. + * Note that pci_cfgregopen() thinks we have PCI devices.. + */ + if (!found) { + if (bootverbose) + printf( + "legacy_pcib_identify: no bridge found, adding pcib0 anyway\n"); + child = BUS_ADD_CHILD(parent, 100, "pcib", 0); + legacy_set_pcibus(child, 0); + } +} + +static int +legacy_pcib_probe(device_t dev) +{ + + if (pci_cfgregopen() == 0) + return ENXIO; + return -100; +} + +static int +legacy_pcib_attach(device_t dev) +{ +#ifdef __HAVE_PIR + device_t pir; +#endif + int bus; + + bus = pcib_get_bus(dev); +#ifdef __HAVE_PIR + /* + * Look for a PCI BIOS interrupt routing table as that will be + * our method of routing interrupts if we have one. + */ + if (pci_pir_probe(bus, 0)) { + pir = BUS_ADD_CHILD(device_get_parent(dev), 0, "pir", 0); + if (pir != NULL) + device_probe_and_attach(pir); + } +#endif + device_add_child(dev, "pci", bus); + return bus_generic_attach(dev); +} + +int +legacy_pcib_read_ivar(device_t dev, device_t child, int which, + uintptr_t *result) +{ + + switch (which) { + case PCIB_IVAR_DOMAIN: + *result = 0; + return 0; + case PCIB_IVAR_BUS: + *result = legacy_get_pcibus(dev); + return 0; + } + return ENOENT; +} + +int +legacy_pcib_write_ivar(device_t dev, device_t child, int which, + uintptr_t value) +{ + + switch (which) { + case PCIB_IVAR_DOMAIN: + return EINVAL; + case PCIB_IVAR_BUS: + legacy_set_pcibus(dev, value); + return 0; + } + return ENOENT; +} + +/* + * Helper routine for x86 Host-PCI bridge driver resource allocation. + * This is used to adjust the start address of wildcard allocation + * requests to avoid low addresses that are known to be problematic. + * + * If no memory preference is given, use upper 32MB slot most BIOSes + * use for their memory window. This is typically only used on older + * laptops that don't have PCI busses behind a PCI bridge, so assuming + * > 32MB is likely OK. + * + * However, this can cause problems for other chipsets, so we make + * this tunable by hw.pci.host_mem_start. + */ +SYSCTL_DECL(_hw_pci); + +static unsigned long host_mem_start = 0x80000000; +TUNABLE_ULONG("hw.pci.host_mem_start", &host_mem_start); +SYSCTL_ULONG(_hw_pci, OID_AUTO, host_mem_start, CTLFLAG_RDTUN, &host_mem_start, + 0, "Limit the host bridge memory to being above this address."); + +u_long +hostb_alloc_start(int type, u_long start, u_long end, u_long count) +{ + + if (start + count - 1 != end) { + if (type == SYS_RES_MEMORY && start < host_mem_start) + start = host_mem_start; + if (type == SYS_RES_IOPORT && start < 0x1000) + start = 0x1000; + } + return (start); +} + +struct resource * +legacy_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + + start = hostb_alloc_start(type, start, end, count); + return (bus_generic_alloc_resource(dev, child, type, rid, start, end, + count, flags)); +} + +static device_method_t legacy_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, legacy_pcib_identify), + DEVMETHOD(device_probe, legacy_pcib_probe), + DEVMETHOD(device_attach, legacy_pcib_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, legacy_pcib_read_ivar), + DEVMETHOD(bus_write_ivar, legacy_pcib_write_ivar), + DEVMETHOD(bus_alloc_resource, legacy_pcib_alloc_resource), + DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, legacy_pcib_maxslots), + DEVMETHOD(pcib_read_config, legacy_pcib_read_config), + DEVMETHOD(pcib_write_config, legacy_pcib_write_config), + DEVMETHOD(pcib_route_interrupt, legacy_pcib_route_interrupt), + DEVMETHOD(pcib_alloc_msi, legacy_pcib_alloc_msi), + DEVMETHOD(pcib_release_msi, pcib_release_msi), + DEVMETHOD(pcib_alloc_msix, legacy_pcib_alloc_msix), + DEVMETHOD(pcib_release_msix, pcib_release_msix), + DEVMETHOD(pcib_map_msi, legacy_pcib_map_msi), + + { 0, 0 } +}; + +static devclass_t hostb_devclass; + +DEFINE_CLASS_0(pcib, legacy_pcib_driver, legacy_pcib_methods, 1); +DRIVER_MODULE(pcib, legacy, legacy_pcib_driver, hostb_devclass, 0, 0); + + +/* + * Install placeholder to claim the resources owned by the + * PCI bus interface. This could be used to extract the + * config space registers in the extreme case where the PnP + * ID is available and the PCI BIOS isn't, but for now we just + * eat the PnP ID and do nothing else. + * + * XXX we should silence this probe, as it will generally confuse + * people. + */ +static struct isa_pnp_id pcibus_pnp_ids[] = { + { 0x030ad041 /* PNP0A03 */, "PCI Bus" }, + { 0x080ad041 /* PNP0A08 */, "PCIe Bus" }, + { 0 } +}; + +static int +pcibus_pnp_probe(device_t dev) +{ + int result; + + if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, pcibus_pnp_ids)) <= 0) + device_quiet(dev); + return(result); +} + +static int +pcibus_pnp_attach(device_t dev) +{ + return(0); +} + +static device_method_t pcibus_pnp_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pcibus_pnp_probe), + DEVMETHOD(device_attach, pcibus_pnp_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + { 0, 0 } +}; + +static devclass_t pcibus_pnp_devclass; + +DEFINE_CLASS_0(pcibus_pnp, pcibus_pnp_driver, pcibus_pnp_methods, 1); +DRIVER_MODULE(pcibus_pnp, isa, pcibus_pnp_driver, pcibus_pnp_devclass, 0, 0); + +#ifdef __HAVE_PIR +/* + * Provide a PCI-PCI bridge driver for PCI busses behind PCI-PCI bridges + * that appear in the PCIBIOS Interrupt Routing Table to use the routing + * table for interrupt routing when possible. + */ +static int pcibios_pcib_probe(device_t bus); + +static device_method_t pcibios_pcib_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pcibios_pcib_probe), + + /* pcib interface */ + DEVMETHOD(pcib_route_interrupt, legacy_pcib_route_interrupt), + + {0, 0} +}; + +static devclass_t pcib_devclass; + +DEFINE_CLASS_1(pcib, pcibios_pcib_driver, pcibios_pcib_pci_methods, + sizeof(struct pcib_softc), pcib_driver); +DRIVER_MODULE(pcibios_pcib, pci, pcibios_pcib_driver, pcib_devclass, 0, 0); + +static int +pcibios_pcib_probe(device_t dev) +{ + int bus; + + if ((pci_get_class(dev) != PCIC_BRIDGE) || + (pci_get_subclass(dev) != PCIS_BRIDGE_PCI)) + return (ENXIO); + bus = pci_read_config(dev, PCIR_SECBUS_1, 1); + if (bus == 0) + return (ENXIO); + if (!pci_pir_probe(bus, 1)) + return (ENXIO); + device_set_desc(dev, "PCIBIOS PCI-PCI bridge"); + return (-2000); +} +#endif -- cgit v1.1 From da3820480591190db96ab7683ee5d3f085cdb7e2 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Wed, 22 Jun 2011 21:10:12 +0000 Subject: Plug an mbuf leak in the new NFS client that occurred when a server replied NFS3ERR_JUKEBOX/NFS4ERR_DELAY to an rpc. This affected both NFSv3 and NFSv4. Found during testing at the recent NFSv4 interoperability Bakeathon. MFC after: 2 weeks --- sys/fs/nfs/nfs_commonkrpc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c index c34ea87..f658ac8 100644 --- a/sys/fs/nfs/nfs_commonkrpc.c +++ b/sys/fs/nfs/nfs_commonkrpc.c @@ -733,6 +733,8 @@ tryagain: while (NFSD_MONOSEC < waituntil) (void) nfs_catnap(PZERO, 0, "nfstry"); trylater_delay *= 2; + m_freem(nd->nd_mrep); + nd->nd_mrep = NULL; goto tryagain; } -- cgit v1.1 From cc2a8545085333500e75f216bbaa6fa3ff7c0a71 Mon Sep 17 00:00:00 2001 From: will Date: Wed, 22 Jun 2011 21:43:10 +0000 Subject: Plumb support for the device advanced information CCB in the ATA XPT. This was previously done only for SCSI XPT in r223081, on which the change in r223089 depended in order to respond to serial number requests. As a result of r223089, da(4) and ada(4) devices register a d_getattr for geom to use to obtain the information. Reported by: ache Reviewed by: ken --- sys/cam/ata/ata_xpt.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index d02b36f..216805d 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -1601,6 +1601,34 @@ ata_device_transport(struct cam_path *path) } static void +ata_dev_advinfo(union ccb *start_ccb) +{ + struct cam_ed *device; + struct ccb_dev_advinfo *cdai; + off_t amt; + + start_ccb->ccb_h.status = CAM_REQ_INVALID; + device = start_ccb->ccb_h.path->device; + cdai = &start_ccb->cdai; + switch(cdai->buftype) { + case CDAI_TYPE_SERIAL_NUM: + if (cdai->flags & CDAI_FLAG_STORE) + break; + start_ccb->ccb_h.status = CAM_REQ_CMP; + cdai->provsiz = device->serial_num_len; + if (device->serial_num_len == 0) + break; + amt = device->serial_num_len; + if (cdai->provsiz > cdai->bufsiz) + amt = cdai->bufsiz; + memcpy(cdai->buf, device->serial_num, amt); + break; + default: + break; + } +} + +static void ata_action(union ccb *start_ccb) { @@ -1652,6 +1680,11 @@ ata_action(union ccb *start_ccb) } /* FALLTHROUGH */ } + case XPT_DEV_ADVINFO: + { + ata_dev_advinfo(start_ccb); + break; + } default: xpt_action_default(start_ccb); break; -- cgit v1.1 From 4faa76d3cae46ac5a82b02f77bceeae3fa446eb6 Mon Sep 17 00:00:00 2001 From: rodrigc Date: Wed, 22 Jun 2011 21:53:45 +0000 Subject: Clarify tftpd's -d flag in the new TFTP implementation. Bump date. --- libexec/tftpd/tftpd.8 | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8 index 3bac492..68168e3 100644 --- a/libexec/tftpd/tftpd.8 +++ b/libexec/tftpd/tftpd.8 @@ -32,7 +32,7 @@ .\" @(#)tftpd.8 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd September 14, 2000 +.Dd June 22, 2011 .Dt TFTPD 8 .Os .Sh NAME @@ -150,9 +150,27 @@ compatible format string for the creation of the suffix if .Fl W is specified. By default the string "%Y%m%d" is used. -.It Fl d +.It Fl d, d Ar [value] Enables debug output. -If specified twice, it will log DATA and ACK packets too. +If +.Ar value +is not specified, then the debug level is increased by one +for each instance of +.Fl d +which is specified. +.Pp +If +.Ar value +is specified, then the debug level is set to +.Ar value . +The debug level is a bitmask implemented in +.Pa src/libexec/tftpd/tftp-utils.h . +Valid values are 0 (DEBUG_NONE), 1 (DEBUG_PACKETS), 2, (DEBUG_SIMPLE), +4 (DEBUG_OPTIONS), and 8 (DEBUG_ACCESS). Multiple debug values can be combined +in the bitmask by logically OR'ing the values. For example, specifying +.Fl d +.Ar 15 +will enable all the debug values. .It Fl l Log all requests using .Xr syslog 3 -- cgit v1.1 From 58522ee4969364dac5ba0a8e8c1e407c7941e617 Mon Sep 17 00:00:00 2001 From: rodrigc Date: Wed, 22 Jun 2011 22:05:37 +0000 Subject: Fix typo. Reported by: Nick Mann --- libexec/tftpd/tftpd.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8 index 68168e3..3befa73 100644 --- a/libexec/tftpd/tftpd.8 +++ b/libexec/tftpd/tftpd.8 @@ -273,7 +273,7 @@ was introduced in .Fx 7.4 . .Sh NOTES Files larger than 33488896 octets (65535 blocks) cannot be transferred -without client and server supporting the the TFTP blocksize option (RFC2348), +without client and server supporting the TFTP blocksize option (RFC2348), or the non-standard TFTP rollover option. .Pp Many tftp clients will not transfer files over 16744448 octets (32767 blocks). -- cgit v1.1 From daed4e9597244449d23c636e25c134076390fd21 Mon Sep 17 00:00:00 2001 From: gavin Date: Wed, 22 Jun 2011 22:08:55 +0000 Subject: Use USB_VENDOR_OVISLINK define rather than the vendor ID. PR: usb/158142 Submitted by: Robert Millan MFC after: 1 week --- sys/dev/usb/wlan/if_urtw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index 3de2273..7805c2d 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -115,7 +115,7 @@ static const struct usb_device_id urtw_devs[] = { URTW_DEV_L(REALTEK, RTL8187), URTW_DEV_L(SITECOMEU, WL168V1), URTW_DEV_L(SURECOM, EP9001G2A), - { USB_VPI(0x1b75, 0x8187, URTW_REV_RTL8187L) }, + { USB_VPI(USB_VENDOR_OVISLINK, 0x8187, URTW_REV_RTL8187L) }, { USB_VPI(USB_VENDOR_DICKSMITH, 0x9401, URTW_REV_RTL8187L) }, { USB_VPI(USB_VENDOR_HP, 0xca02, URTW_REV_RTL8187L) }, { USB_VPI(USB_VENDOR_LOGITEC, 0x010c, URTW_REV_RTL8187L) }, -- cgit v1.1 From ecea455f28b101465b759c50e88b60b57d4a9fba Mon Sep 17 00:00:00 2001 From: rodrigc Date: Wed, 22 Jun 2011 22:55:51 +0000 Subject: Bump date. Document the following commands which were added in the new TFTP implementation: blocksize, blocksize2, packetdrop, options, rollover --- usr.bin/tftp/tftp.1 | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/usr.bin/tftp/tftp.1 b/usr.bin/tftp/tftp.1 index bf8720b..494054b 100644 --- a/usr.bin/tftp/tftp.1 +++ b/usr.bin/tftp/tftp.1 @@ -28,7 +28,7 @@ .\" @(#)tftp.1 8.2 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd October 1, 2003 +.Dd June 22, 2011 .Dt TFTP 1 .Os .Sh NAME @@ -70,6 +70,21 @@ Shorthand for "mode ascii" .It Cm binary Shorthand for "mode binary" .Pp +.It Cm blocksize Ar [size] +Sets the TFTP blksize option in TFTP Read Request or Write Request packets +to +.Ar [size] +as specified in RFC 2348. Valid values are between 8 and 65464. +If no blocksize is specified, then by default a blocksize of 512 bytes +will be used. +.Pp +.It Cm blocksize2 Ar [size] +Sets the TFTP blksize2 option in TFTP Read Request or Write Request packets +to +.Ar [size] . +Values are restricted to powers of 2 between 8 and 32768. This is a +non-standard TFTP option. +.Pp .It Cm connect Ar host Op Ar port Set the .Ar host @@ -93,6 +108,14 @@ or .Cm put commands. .Pp +.It Cm debug Ar level +Enable or disable debugging levels during verbose output. The value of +.Ar level +can be one of +.Cm packet, simple, options, +or +.Cm access. +.Pp .It Cm get Oo Ar host : Oc Ns Ar file Op Ar localname .It Cm get Xo .Oo Ar host1 : Oc Ns Ar file1 @@ -130,6 +153,11 @@ or The default is .Em ascii . .Pp +.It Cm packetdrop [arg] +Randomly drop +.Ar arg +out of 100 packets during a transfer. This is a debugging feature. +.Pp .It Cm put Ar file Op Oo Ar host : Oc Ns Ar remotename .It Cm put Ar file1 file2 ... fileN Op Oo Ar host : Oc Ns Ar remote-directory Put a file or set of files to the remote host. @@ -149,6 +177,17 @@ see the example under the .Cm get command. .Pp +.It Cm options Ar [arg] +Enable or disable support for TFTP options. The valid values of +.Ar arg +are +.Cm on +(enable RFC 2347 options), +.Cm off +(disable RFC 2347 options), and +.Cm extra +(toggle support for non-RFC defined options). +.Pp .It Cm quit Exit .Nm . @@ -157,6 +196,15 @@ An end of file also exits. .It Cm rexmt Ar retransmission-timeout Set the per-packet retransmission timeout, in seconds. .Pp +.It Cm rollover [arg] +Specify the rollover option in TFTP Read Request or Write +Request packets. After 65535 packets have been transmitted, set the block +counter to +.Ar arg . +Valid values of +.Ar arg +are 0 and 1. This is a non-standard TFTP option. +.Pp .It Cm status Show current status. .Pp -- cgit v1.1 From 32b96d68087da77d33ebe05b2ff29b320276da71 Mon Sep 17 00:00:00 2001 From: will Date: Wed, 22 Jun 2011 22:55:51 +0000 Subject: Return CAM_REQ_INVALID if the SCSI XPT receives an unsupported operation via the XPT_DEV_ADVINFO CCB. Reviewed by: ken --- sys/cam/scsi/scsi_xpt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 1b507ca..c1f713b 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -2440,12 +2440,13 @@ scsi_dev_advinfo(union ccb *start_ccb) struct ccb_dev_advinfo *cdai; off_t amt; + start_ccb->ccb_h.status = CAM_REQ_INVALID; device = start_ccb->ccb_h.path->device; cdai = &start_ccb->cdai; switch(cdai->buftype) { case CDAI_TYPE_SCSI_DEVID: if (cdai->flags & CDAI_FLAG_STORE) - break; + return; cdai->provsiz = device->device_id_len; if (device->device_id_len == 0) break; @@ -2456,7 +2457,7 @@ scsi_dev_advinfo(union ccb *start_ccb) break; case CDAI_TYPE_SERIAL_NUM: if (cdai->flags & CDAI_FLAG_STORE) - break; + return; cdai->provsiz = device->serial_num_len; if (device->serial_num_len == 0) break; @@ -2490,7 +2491,7 @@ scsi_dev_advinfo(union ccb *start_ccb) } break; default: - break; + return; } start_ccb->ccb_h.status = CAM_REQ_CMP; -- cgit v1.1 From d1e97d2773931873cc7fbc821c7d4fd33d9e6de7 Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 22 Jun 2011 22:56:42 +0000 Subject: Fix build on ia64 after r223426. --- sys/dev/acpica/acpi_cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c index 583b548..b0a7210 100644 --- a/sys/dev/acpica/acpi_cpu.c +++ b/sys/dev/acpica/acpi_cpu.c @@ -856,8 +856,10 @@ acpi_cpu_cx_list(struct acpi_cpu_softc *sc) sbuf_printf(&sb, "C%d/%d ", i + 1, sc->cpu_cx_states[i].trans_lat); if (sc->cpu_cx_states[i].type < ACPI_STATE_C3) sc->cpu_non_c3 = i; +#ifndef __ia64__ else cpu_can_deep_sleep = 1; +#endif } sbuf_trim(&sb); sbuf_finish(&sb); -- cgit v1.1 From e4d159c9630d6c6aab4bf9e8a81f85a827c675a9 Mon Sep 17 00:00:00 2001 From: rodrigc Date: Wed, 22 Jun 2011 23:25:24 +0000 Subject: Update references to RFC's that the newer TFTP implementation supports. --- libexec/tftpd/tftpd.8 | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8 index 3befa73..c8474d2 100644 --- a/libexec/tftpd/tftpd.8 +++ b/libexec/tftpd/tftpd.8 @@ -235,12 +235,34 @@ option. .Xr services 5 , .Xr syslog.conf 5 , .Xr inetd 8 +.Pp +The following RFC's are supported: .Rs -.%A K. R. Sollins +RFC 1350 .%T The TFTP Protocol (Revision 2) -.%D July 1992 -.%O RFC 1350, STD 33 .Re +.Rs +RFC 2347 +.%T TFTP Option Extension +.Re +.Rs +RFC 2348 +.%T TFTP Blocksize Option +.Re +.Rs +RFC 2349 +.%T TFTP Timeout Interval and Transfer Size Options +.Re +.Pp +The non-standard +.Cm rollover +and +.Cm blksize2 +TFTP options are mentioned here: +.Rs +.%T Extending TFTP +.%U http://www.compuphase.com/tftp.htm +.Re .Sh HISTORY The .Nm -- cgit v1.1 From 0aadb5ac8fd16758a1dd82c0f56378b593f27630 Mon Sep 17 00:00:00 2001 From: rodrigc Date: Wed, 22 Jun 2011 23:26:04 +0000 Subject: Update references to RFC's that the newer TFTP implementation supports. --- usr.bin/tftp/tftp.1 | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/usr.bin/tftp/tftp.1 b/usr.bin/tftp/tftp.1 index 494054b..8c58352 100644 --- a/usr.bin/tftp/tftp.1 +++ b/usr.bin/tftp/tftp.1 @@ -217,6 +217,40 @@ Toggle packet tracing. .It Cm verbose Toggle verbose mode. .El +.Sh SEE ALSO +.Xr tftp 1 +.Pp +The following RFC's are supported: +.Rs +RFC 1350 +.%T The TFTP Protocol (Revision 2) +.Re +.Rs +RFC 2347 +.%T TFTP Option Extension +.Re +.Rs +RFC 2348 +.%T TFTP Blocksize Option +.Re +.Rs +RFC 2349 +.%T TFTP Timeout Interval and Transfer Size Options +.Re +.Rs +RFC 3617 +.%T Uniform Resource Identifier (URI) Scheme and Applicability Statement for the Trivial File Transfer Protocol (TFTP) +.Re +.Pp +The non-standard +.Cm rollover +and +.Cm blksize2 +TFTP options are mentioned here: +.Rs +.%T Extending TFTP +.%U http://www.compuphase.com/tftp.htm +.Re .Sh HISTORY The .Nm -- cgit v1.1 From 6bed1e8b264c688cd422e56d1c3d1747a6e22da2 Mon Sep 17 00:00:00 2001 From: hrs Date: Thu, 23 Jun 2011 02:35:55 +0000 Subject: Remove links to mirrorlist.FreeBSD.org. Submitted by: ryusuke Reported by: gavin, brucec --- release/doc/en_US.ISO8859-1/readme/article.sgml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/release/doc/en_US.ISO8859-1/readme/article.sgml b/release/doc/en_US.ISO8859-1/readme/article.sgml index 33ae82c..f8ba3aa 100644 --- a/release/doc/en_US.ISO8859-1/readme/article.sgml +++ b/release/doc/en_US.ISO8859-1/readme/article.sgml @@ -184,8 +184,7 @@ Lists of locations that mirror &os; can be found in the FTP - Sites section of the Handbook, or on the Web pages. + Sites section of the Handbook. Finding a close (in networking terms) mirror from which to download the distribution is highly recommended. -- cgit v1.1 From b6944718e6937ccf5ca5426ff8350b39f3fc85c2 Mon Sep 17 00:00:00 2001 From: hrs Date: Thu, 23 Jun 2011 02:38:06 +0000 Subject: Bump &release.manpath.*;. --- release/doc/share/sgml/release.ent | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/doc/share/sgml/release.ent b/release/doc/share/sgml/release.ent index 0a4c1ce..60b7130 100644 --- a/release/doc/share/sgml/release.ent +++ b/release/doc/share/sgml/release.ent @@ -36,8 +36,8 @@ - - + + -- cgit v1.1 From 014faf03464315d298a8b2f06f6184ccdaa7b1cf Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 23 Jun 2011 02:38:36 +0000 Subject: Break out most of the HAL related tweaks into a per-HAL instance, rather than global variables. This specifically allows for debugging to be enabled per-NIC, rather than globally. Since the ath driver doesn't know about AH_DEBUG, and to keep the ABI consistent regardless of whether AH_DEBUG is enabled or not, enable the debug parameter always but only conditionally compile in the debug methods if needed. The ALQ support is currently still global pending some brainstorming. Submitted by: ssgriffonuser@gmail.com Reviewed by: adrian, bschmidt --- sys/dev/ath/ah_osdep.c | 31 +++-------------------- sys/dev/ath/ath_hal/ah.h | 12 +++++++++ sys/dev/ath/ath_hal/ah_internal.h | 9 +------ sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c | 4 +-- sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c | 4 +-- sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c | 5 ++-- sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c | 4 +-- sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c | 6 ++--- sys/dev/ath/ath_hal/ar5416/ar2133.c | 2 +- sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c | 4 +-- sys/dev/ath/ath_hal/ar5416/ar5416_misc.c | 2 +- sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c | 6 ++--- sys/dev/ath/if_ath.c | 1 + sys/dev/ath/if_ath_sysctl.c | 40 ++++++++++++++++++++++++++++++ sys/dev/ath/if_ath_sysctl.h | 2 +- 15 files changed, 77 insertions(+), 55 deletions(-) diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c index b14bba0..c0f9b8c 100644 --- a/sys/dev/ath/ah_osdep.c +++ b/sys/dev/ath/ah_osdep.c @@ -76,33 +76,6 @@ extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...); /* NB: put this here instead of the driver to avoid circular references */ SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters"); -SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, "Atheros HAL parameters"); - -#ifdef AH_DEBUG -int ath_hal_debug = 0; -SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug, - 0, "Atheros HAL debugging printfs"); -TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug); -#endif /* AH_DEBUG */ - -int ath_hal_ar5416_biasadj = 0; -SYSCTL_INT(_hw_ath_hal, OID_AUTO, ar5416_biasadj, CTLFLAG_RW, - &ath_hal_ar5416_biasadj, 0, "Enable 2ghz AR5416 direction sensitivity" - " bias adjust"); - -/* NB: these are deprecated; they exist for now for compatibility */ -int ath_hal_dma_beacon_response_time = 2; /* in TU's */ -SYSCTL_INT(_hw_ath_hal, OID_AUTO, dma_brt, CTLFLAG_RW, - &ath_hal_dma_beacon_response_time, 0, - "Atheros HAL DMA beacon response time"); -int ath_hal_sw_beacon_response_time = 10; /* in TU's */ -SYSCTL_INT(_hw_ath_hal, OID_AUTO, sw_brt, CTLFLAG_RW, - &ath_hal_sw_beacon_response_time, 0, - "Atheros HAL software beacon response time"); -int ath_hal_additional_swba_backoff = 0; /* in TU's */ -SYSCTL_INT(_hw_ath_hal, OID_AUTO, swba_backoff, CTLFLAG_RW, - &ath_hal_additional_swba_backoff, 0, - "Atheros HAL additional SWBA backoff time"); MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data"); @@ -146,7 +119,7 @@ ath_hal_ether_sprintf(const u_int8_t *mac) void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) { - if ((mask == HAL_DEBUG_UNMASKABLE) || (ath_hal_debug & mask)) { + if ((mask == HAL_DEBUG_UNMASKABLE) || (ah->ah_config.ah_debug & mask)) { __va_list ap; va_start(ap, fmt); ath_hal_vprintf(ah, fmt, ap); @@ -174,6 +147,8 @@ DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) #include #include +SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, "Atheros HAL parameters"); + static struct alq *ath_hal_alq; static int ath_hal_alq_emitdev; /* need to emit DEVICE record */ static u_int ath_hal_alq_lost; /* count of lost records */ diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h index 7a01be3..f81e6aa 100644 --- a/sys/dev/ath/ath_hal/ah.h +++ b/sys/dev/ath/ath_hal/ah.h @@ -756,6 +756,17 @@ struct dfs_event { }; typedef struct dfs_event HAL_DFS_EVENT; +typedef struct +{ + int ah_debug; /* only used if AH_DEBUG is defined */ + int ah_ar5416_biasadj; /* enable AR2133 radio specific bias fiddling */ + + /* NB: these are deprecated; they exist for now for compatibility */ + int ah_dma_beacon_response_time;/* in TU's */ + int ah_sw_beacon_response_time; /* in TU's */ + int ah_additional_swba_backoff; /* in TU's */ +}HAL_OPS_CONFIG; + /* * Hardware Access Layer (HAL) API. * @@ -784,6 +795,7 @@ struct ath_hal { uint16_t *ah_eepromdata; /* eeprom buffer, if needed */ + HAL_OPS_CONFIG ah_config; const HAL_RATE_TABLE *__ahdecl(*ah_getRateTable)(struct ath_hal *, u_int mode); void __ahdecl(*ah_detach)(struct ath_hal*); diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h index d66c9d8..91edc34 100644 --- a/sys/dev/ath/ath_hal/ah_internal.h +++ b/sys/dev/ath/ath_hal/ah_internal.h @@ -475,12 +475,6 @@ isBigEndian(void) #define OS_A_REG_RMW_FIELD(_a, _r, _f, _v) \ do { OS_REG_WRITE(_a, _r, (OS_REG_READ(_a, _r) &~ (_f)) | (((_v) << _f##_S) & (_f))) ; OS_DELAY(100); } while (0) -/* system-configurable parameters */ -extern int ath_hal_dma_beacon_response_time; /* in TU's */ -extern int ath_hal_sw_beacon_response_time; /* in TU's */ -extern int ath_hal_additional_swba_backoff; /* in TU's */ -extern int ath_hal_ar5416_biasadj; /* 1 or 0 */ - /* wait for the register contents to have the specified value */ extern HAL_BOOL ath_hal_wait(struct ath_hal *, u_int reg, uint32_t mask, uint32_t val); @@ -504,11 +498,10 @@ extern void ath_hal_free(void *); /* common debugging interfaces */ #ifdef AH_DEBUG #include "ah_debug.h" -extern int ath_hal_debug; #define HALDEBUG(_ah, __m, ...) \ do { \ if ((__m) == HAL_DEBUG_UNMASKABLE || \ - (ath_hal_debug & (__m))) { \ + ((_ah != AH_NULL) && (((struct ath_hal*)_ah)->ah_config.ah_debug & (__m)))) { \ DO_HALDEBUG((_ah), (__m), __VA_ARGS__); \ } \ } while(0); diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c index dbd059e..a613c9c 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c @@ -56,9 +56,9 @@ ar5210BeaconInit(struct ath_hal *ah, if (AH_PRIVATE(ah)->ah_opmode != HAL_M_STA) { bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ /* * The SWBA interrupt is not used for beacons in ad hoc mode * as we don't yet support ATIMs. So since the beacon never diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c b/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c index 669b8f6..31e9c5d 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c @@ -71,9 +71,9 @@ ar5211BeaconInit(struct ath_hal *ah, case HAL_M_IBSS: case HAL_M_HOSTAP: bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ break; } /* diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c b/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c index 3af314f..e1e7f73 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_xmit.c @@ -345,8 +345,9 @@ ar5211ResetTxQueue(struct ath_hal *ah, u_int q) | AR_Q_MISC_CBR_INCR_DIS0 | AR_Q_MISC_RDYTIME_EXP_POLICY); value = (ahp->ah_beaconInterval - - (ath_hal_sw_beacon_response_time - ath_hal_dma_beacon_response_time) - - ath_hal_additional_swba_backoff) * 1024; + - (ah->ah_config.ah_sw_beacon_response_time + - ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff) * 1024; OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_EN); /* Configure DCU for CAB */ diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c index 538f8b8..6c1937a 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c @@ -84,9 +84,9 @@ ar5212BeaconInit(struct ath_hal *ah, case HAL_M_HOSTAP: case HAL_M_IBSS: bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ break; } /* diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c b/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c index 4fbce31..3c6ddc0 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_xmit.c @@ -416,9 +416,9 @@ ar5212ResetTxQueue(struct ath_hal *ah, u_int q) * here solely for backwards compatibility. */ value = (ahp->ah_beaconInterval - - (ath_hal_sw_beacon_response_time - - ath_hal_dma_beacon_response_time) - - ath_hal_additional_swba_backoff) * 1024; + - (ah->ah_config.ah_sw_beacon_response_time - + ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff) * 1024; OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_ENA); } dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, diff --git a/sys/dev/ath/ath_hal/ar5416/ar2133.c b/sys/dev/ath/ath_hal/ar5416/ar2133.c index f92ea00..f25c108 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar2133.c +++ b/sys/dev/ath/ath_hal/ar5416/ar2133.c @@ -185,7 +185,7 @@ ar2133SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) } /* Workaround for hw bug - AR5416 specific */ - if (AR_SREV_OWL(ah) && ath_hal_ar5416_biasadj) + if (AR_SREV_OWL(ah) && ah->ah_config.ah_ar5416_biasadj) ar2133ForceBias(ah, freq); reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c index 358a0ee..ee6c1eb 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c @@ -93,9 +93,9 @@ ar5416BeaconInit(struct ath_hal *ah, /* fall thru... */ case HAL_M_HOSTAP: bt.bt_nextdba = (next_beacon - - ath_hal_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ath_hal_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_flags |= AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA; diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c index 2332656..6266b58 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c @@ -288,7 +288,7 @@ ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration, nextStart_us += OS_REG_READ(ah, AR_TSF_L32); } if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) { - nextStart_us += ath_hal_sw_beacon_response_time; + nextStart_us += ah->ah_config.ah_sw_beacon_response_time; } OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR)); diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c index 48956c5..20791e8 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c @@ -1035,9 +1035,9 @@ ar5416ResetTxQueue(struct ath_hal *ah, u_int q) * here solely for backwards compatibility. */ value = (ahp->ah_beaconInterval - - (ath_hal_sw_beacon_response_time - - ath_hal_dma_beacon_response_time) - - ath_hal_additional_swba_backoff) * 1024; + - (ah->ah_config.ah_sw_beacon_response_time - + ah->ah_config.ah_dma_beacon_response_time) + - ah->ah_config.ah_additional_swba_backoff) * 1024; OS_REG_WRITE(ah, AR_QRDYTIMECFG(q), value | AR_Q_RDYTIMECFG_ENA); } dmisc |= SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 6c7b0e7..f3afc70 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -738,6 +738,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) */ ath_sysctlattach(sc); ath_sysctl_stats_attach(sc); + ath_sysctl_hal_attach(sc); if (bootverbose) ieee80211_announce(ic); diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c index 6c1a6b2..e3c9966 100644 --- a/sys/dev/ath/if_ath_sysctl.c +++ b/sys/dev/ath/if_ath_sysctl.c @@ -719,3 +719,43 @@ ath_sysctl_stats_attach(struct ath_softc *sc) /* Attach the RX phy error array */ ath_sysctl_stats_attach_rxphyerr(sc, child); } + +/* + * This doesn't necessarily belong here (because it's HAL related, not + * driver related). + */ +void +ath_sysctl_hal_attach(struct ath_softc *sc) +{ + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); + + tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "hal", CTLFLAG_RD, + NULL, "Atheros HAL parameters"); + child = SYSCTL_CHILDREN(tree); + + sc->sc_ah->ah_config.ah_debug = 0; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "debug", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_debug, 0, "Atheros HAL debugging printfs"); + + sc->sc_ah->ah_config.ah_ar5416_biasadj = 0; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "ar5416_biasadj", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_ar5416_biasadj, 0, + "Enable 2ghz AR5416 direction sensitivity bias adjust"); + + sc->sc_ah->ah_config.ah_dma_beacon_response_time = 2; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "dma_brt", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_dma_beacon_response_time, 0, + "Atheros HAL DMA beacon response time"); + + sc->sc_ah->ah_config.ah_sw_beacon_response_time = 10; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "sw_brt", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_sw_beacon_response_time, 0, + "Atheros HAL software beacon response time"); + + sc->sc_ah->ah_config.ah_additional_swba_backoff = 0; + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "swba_backoff", CTLFLAG_RW, + &sc->sc_ah->ah_config.ah_additional_swba_backoff, 0, + "Atheros HAL additional SWBA backoff time"); +} diff --git a/sys/dev/ath/if_ath_sysctl.h b/sys/dev/ath/if_ath_sysctl.h index f96a73e..1fef2be 100644 --- a/sys/dev/ath/if_ath_sysctl.h +++ b/sys/dev/ath/if_ath_sysctl.h @@ -34,5 +34,5 @@ extern void ath_sysctlattach(struct ath_softc *); extern void ath_sysctl_stats_attach(struct ath_softc *sc); - +extern void ath_sysctl_hal_attach(struct ath_softc *sc); #endif -- cgit v1.1 From d2b9ceb5222a753c78eaae12244828f5799af35a Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 23 Jun 2011 03:20:11 +0000 Subject: Add hypervisor call error codes. --- sys/powerpc/ps3/ps3-hvcall.h | 28 ++++++++++++++++++++++++++++ sys/powerpc/ps3/ps3-hvcall.master | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/sys/powerpc/ps3/ps3-hvcall.h b/sys/powerpc/ps3/ps3-hvcall.h index 912158b..0875a62 100644 --- a/sys/powerpc/ps3/ps3-hvcall.h +++ b/sys/powerpc/ps3/ps3-hvcall.h @@ -11,6 +11,34 @@ enum lpar_id { PS3_LPAR_ID_PME = 0x01, }; +/* Return codes from hypercalls */ +#define LV1_SUCCESS 0 +#define LV1_RESOURCE_SHORTAGE -2 +#define LV1_NO_PRIVILEGE -3 +#define LV1_DENIED_BY_POLICY -4 +#define LV1_ACCESS_VIOLATION -5 +#define LV1_NO_ENTRY -6 +#define LV1_DUPLICATE_ENTRY -7 +#define LV1_TYPE_MISMATCH -8 +#define LV1_BUSY -9 +#define LV1_EMPTY -10 +#define LV1_WRONG_STATE -11 +#define LV1_NO_MATCH -13 +#define LV1_ALREADY_CONNECTED -14 +#define LV1_UNSUPPORTED_PARAMETER_VALUE -15 +#define LV1_CONDITION_NOT_SATISFIED -16 +#define LV1_ILLEGAL_PARAMETER_VALUE -17 +#define LV1_BAD_OPTION -18 +#define LV1_IMPLEMENTATION_LIMITATION -19 +#define LV1_NOT_IMPLEMENTED -20 +#define LV1_INVALID_CLASS_ID -21 +#define LV1_CONSTRAINT_NOT_SATISFIED -22 +#define LV1_ALIGNMENT_ERROR -23 +#define LV1_HARDWARE_ERROR -24 +#define LV1_INVALID_DATA_FORMAT -25 +#define LV1_INVALID_OPERATION -26 +#define LV1_INTERNAL_ERROR -32768 + static inline uint64_t lv1_repository_string(const char *str) { diff --git a/sys/powerpc/ps3/ps3-hvcall.master b/sys/powerpc/ps3/ps3-hvcall.master index d53a32e..a9abe94 100644 --- a/sys/powerpc/ps3/ps3-hvcall.master +++ b/sys/powerpc/ps3/ps3-hvcall.master @@ -11,6 +11,34 @@ enum lpar_id { PS3_LPAR_ID_PME = 0x01, }; +/* Return codes from hypercalls */ +#define LV1_SUCCESS 0 +#define LV1_RESOURCE_SHORTAGE -2 +#define LV1_NO_PRIVILEGE -3 +#define LV1_DENIED_BY_POLICY -4 +#define LV1_ACCESS_VIOLATION -5 +#define LV1_NO_ENTRY -6 +#define LV1_DUPLICATE_ENTRY -7 +#define LV1_TYPE_MISMATCH -8 +#define LV1_BUSY -9 +#define LV1_EMPTY -10 +#define LV1_WRONG_STATE -11 +#define LV1_NO_MATCH -13 +#define LV1_ALREADY_CONNECTED -14 +#define LV1_UNSUPPORTED_PARAMETER_VALUE -15 +#define LV1_CONDITION_NOT_SATISFIED -16 +#define LV1_ILLEGAL_PARAMETER_VALUE -17 +#define LV1_BAD_OPTION -18 +#define LV1_IMPLEMENTATION_LIMITATION -19 +#define LV1_NOT_IMPLEMENTED -20 +#define LV1_INVALID_CLASS_ID -21 +#define LV1_CONSTRAINT_NOT_SATISFIED -22 +#define LV1_ALIGNMENT_ERROR -23 +#define LV1_HARDWARE_ERROR -24 +#define LV1_INVALID_DATA_FORMAT -25 +#define LV1_INVALID_OPERATION -26 +#define LV1_INTERNAL_ERROR -32768 + static inline uint64_t lv1_repository_string(const char *str) { -- cgit v1.1 From 92790aaa8760da434387dac80633830e0948f088 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 23 Jun 2011 03:37:25 +0000 Subject: Rework the PS3 disk driver to support NCQ and do its DMA a little differently. --- sys/powerpc/ps3/ps3disk.c | 577 +++++++++++++++------------------------------- 1 file changed, 189 insertions(+), 388 deletions(-) diff --git a/sys/powerpc/ps3/ps3disk.c b/sys/powerpc/ps3/ps3disk.c index 5390f50..3bab0f2 100644 --- a/sys/powerpc/ps3/ps3disk.c +++ b/sys/powerpc/ps3/ps3disk.c @@ -116,39 +116,25 @@ struct ps3disk_softc { struct disk **sc_disk; struct bio_queue_head sc_bioq; + struct bio_queue_head sc_deferredq; + struct proc *sc_task; - struct proc *sc_task; - - int sc_bounce_maxblocks; - bus_dma_tag_t sc_bounce_dmatag; - bus_dmamap_t sc_bounce_dmamap; - bus_addr_t sc_bounce_dmaphys; - char *sc_bounce; - uint64_t sc_bounce_lpar; - int sc_bounce_busy; - uint64_t sc_bounce_tag; - uint64_t sc_bounce_status; + bus_dma_tag_t sc_dmatag; int sc_running; - int sc_debug; }; static int ps3disk_open(struct disk *dp); static int ps3disk_close(struct disk *dp); static void ps3disk_strategy(struct bio *bp); -static void ps3disk_task(void *arg); -static int ps3disk_intr_filter(void *arg); +static void ps3disk_task(void *arg); static void ps3disk_intr(void *arg); -static void ps3disk_getphys(void *arg, bus_dma_segment_t *segs, int nsegs, int error); static int ps3disk_get_disk_geometry(struct ps3disk_softc *sc); static int ps3disk_enum_regions(struct ps3disk_softc *sc); -static int ps3disk_read(struct ps3disk_softc *sc, int regidx, - uint64_t start_sector, uint64_t sector_count, char *data); -static int ps3disk_write(struct ps3disk_softc *sc, int regidx, - uint64_t start_sector, uint64_t sector_count, char *data); -static int ps3disk_flush(struct ps3disk_softc *sc); +static void ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, + int error); static void ps3disk_sysctlattach(struct ps3disk_softc *sc); @@ -172,6 +158,7 @@ ps3disk_attach(device_t dev) struct ps3disk_softc *sc; struct disk *d; intmax_t mb; + uint64_t junk; char unit; int i, err; @@ -205,7 +192,6 @@ ps3disk_attach(device_t dev) } /* Setup interrupt handler */ - sc->sc_irqid = 0; sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid, RF_ACTIVE); @@ -217,52 +203,24 @@ ps3disk_attach(device_t dev) err = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY, - ps3disk_intr_filter, ps3disk_intr, sc, &sc->sc_irqctx); + NULL, ps3disk_intr, sc, &sc->sc_irqctx); if (err) { device_printf(dev, "Could not setup IRQ\n"); err = ENXIO; goto fail_release_intr; } - /* Setup DMA bounce buffer */ - - sc->sc_bounce_maxblocks = DFLTPHYS / sc->sc_blksize; - + /* Setup DMA */ err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, - sc->sc_bounce_maxblocks * sc->sc_blksize, 1, - sc->sc_bounce_maxblocks * sc->sc_blksize, - 0, NULL, NULL, &sc->sc_bounce_dmatag); + BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0, + busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag); if (err) { - device_printf(dev, "Could not create DMA tag for bounce buffer\n"); + device_printf(dev, "Could not create DMA tag\n"); err = ENXIO; goto fail_teardown_intr; } - err = bus_dmamem_alloc(sc->sc_bounce_dmatag, (void **) &sc->sc_bounce, - BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, - &sc->sc_bounce_dmamap); - if (err) { - device_printf(dev, "Could not allocate DMA memory for bounce buffer\n"); - err = ENXIO; - goto fail_destroy_dmatag; - } - - err = bus_dmamap_load(sc->sc_bounce_dmatag, sc->sc_bounce_dmamap, - sc->sc_bounce, sc->sc_bounce_maxblocks * sc->sc_blksize, - ps3disk_getphys, &sc->sc_bounce_dmaphys, 0); - if (err) { - device_printf(dev, "Could not load DMA map for bounce buffer\n"); - err = ENXIO; - goto fail_free_dmamem; - } - - sc->sc_bounce_lpar = vtophys(sc->sc_bounce); - - if (bootverbose) - device_printf(dev, "bounce buffer lpar address 0x%016lx\n", - sc->sc_bounce_lpar); - /* Setup disks */ sc->sc_disk = malloc(sc->sc_nregs * sizeof(struct disk *), @@ -270,7 +228,7 @@ ps3disk_attach(device_t dev) if (!sc->sc_disk) { device_printf(dev, "Could not allocate disk(s)\n"); err = ENOMEM; - goto fail_unload_dmamem; + goto fail_teardown_intr; } for (i = 0; i < sc->sc_nregs; i++) { @@ -282,7 +240,7 @@ ps3disk_attach(device_t dev) d->d_strategy = ps3disk_strategy; d->d_name = "ps3disk"; d->d_drv1 = sc; - d->d_maxsize = DFLTPHYS; + d->d_maxsize = PAGE_SIZE; d->d_sectorsize = sc->sc_blksize; d->d_unit = i; d->d_mediasize = sc->sc_reg[i].r_size * sc->sc_blksize; @@ -297,53 +255,32 @@ ps3disk_attach(device_t dev) /* Test to see if we can read this region */ err = lv1_storage_read(ps3bus_get_device(dev), d->d_unit, - 0, 1, rp->r_flags, sc->sc_bounce_lpar, &sc->sc_bounce_tag); + 0, 0, rp->r_flags, 0, &junk); device_printf(dev, "region %d %ju%cB%s\n", i, mb, unit, - (err == 0) ? "" : " (hypervisor protected)"); + (err == LV1_DENIED_BY_POLICY) ? " (hypervisor protected)" + : ""); - if (err == 0) + if (err != LV1_DENIED_BY_POLICY) disk_create(d, DISK_VERSION); } err = 0; bioq_init(&sc->sc_bioq); + bioq_init(&sc->sc_deferredq); + kproc_create(&ps3disk_task, sc, &sc->sc_task, 0, 0, "ps3disk"); ps3disk_sysctlattach(sc); - sc->sc_running = 1; - - kproc_create(&ps3disk_task, sc, &sc->sc_task, 0, 0, "task: ps3disk"); - return (0); -fail_unload_dmamem: - - bus_dmamap_unload(sc->sc_bounce_dmatag, sc->sc_bounce_dmamap); - -fail_free_dmamem: - - bus_dmamem_free(sc->sc_bounce_dmatag, sc->sc_bounce, sc->sc_bounce_dmamap); - -fail_destroy_dmatag: - - bus_dma_tag_destroy(sc->sc_bounce_dmatag); - fail_teardown_intr: - bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx); - fail_release_intr: - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq); - fail_free_regions: - free(sc->sc_reg, M_PS3DISK); - fail_destroy_lock: - PS3DISK_LOCK_DESTROY(sc); - return (err); } @@ -353,28 +290,15 @@ ps3disk_detach(device_t dev) struct ps3disk_softc *sc = device_get_softc(dev); int i; - PS3DISK_LOCK(sc); - sc->sc_running = 0; - wakeup(sc); - PS3DISK_UNLOCK(sc); - - PS3DISK_LOCK(sc); - while (sc->sc_running != -1) - msleep(sc, &sc->sc_mtx, PRIBIO, "detach", 0); - PS3DISK_UNLOCK(sc); - for (i = 0; i < sc->sc_nregs; i++) disk_destroy(sc->sc_disk[i]); - bus_dmamap_unload(sc->sc_bounce_dmatag, sc->sc_bounce_dmamap); - bus_dmamem_free(sc->sc_bounce_dmatag, sc->sc_bounce, sc->sc_bounce_dmamap); - bus_dma_tag_destroy(sc->sc_bounce_dmatag); + bus_dma_tag_destroy(sc->sc_dmatag); bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq); free(sc->sc_disk, M_PS3DISK); - free(sc->sc_reg, M_PS3DISK); PS3DISK_LOCK_DESTROY(sc); @@ -394,127 +318,94 @@ ps3disk_close(struct disk *dp) return (0); } -static void -ps3disk_strategy(struct bio *bp) -{ - struct ps3disk_softc *sc = (struct ps3disk_softc *) bp->bio_disk->d_drv1; - - if (!sc) { - bp->bio_flags |= BIO_ERROR; - bp->bio_error = EINVAL; - biodone(bp); - return; - } - - PS3DISK_LOCK(sc); - bioq_disksort(&sc->sc_bioq, bp); - if (!sc->sc_bounce_busy) - wakeup(sc); - PS3DISK_UNLOCK(sc); -} - +/* Process deferred blocks */ static void ps3disk_task(void *arg) { struct ps3disk_softc *sc = (struct ps3disk_softc *) arg; struct bio *bp; - daddr_t block, end; - u_long nblocks; - char *data; - int err; - while (sc->sc_running) { + + while (1) { + kproc_suspend_check(sc->sc_task); + tsleep(&sc->sc_deferredq, PRIBIO, "ps3disk", 10); + PS3DISK_LOCK(sc); - do { - bp = bioq_first(&sc->sc_bioq); - if (bp == NULL) - msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0); - } while (bp == NULL && sc->sc_running); - if (bp) - bioq_remove(&sc->sc_bioq, bp); + bp = bioq_takefirst(&sc->sc_deferredq); PS3DISK_UNLOCK(sc); - if (!sc->sc_running) - break; + if (bp == NULL) + continue; - DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_cmd 0x%02x\n", - __func__, bp->bio_cmd); + if (bp->bio_driver1 != NULL) { + bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t) + bp->bio_driver1); + bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t) + bp->bio_driver1); + } - if (bp->bio_cmd == BIO_FLUSH) { - err = ps3disk_flush(sc); + ps3disk_strategy(bp); + } - if (err) { - bp->bio_error = EIO; - bp->bio_flags |= BIO_ERROR; - } else { - bp->bio_error = 0; - bp->bio_flags |= BIO_DONE; - } - } else if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { - end = bp->bio_pblkno + (bp->bio_bcount / sc->sc_blksize); - - DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_pblkno %ld bio_bcount %ld\n", - __func__, bp->bio_pblkno, bp->bio_bcount); - - for (block = bp->bio_pblkno; block < end;) { - data = bp->bio_data + - (block - bp->bio_pblkno) * sc->sc_blksize; - - nblocks = end - block; - if (nblocks > sc->sc_bounce_maxblocks) - nblocks = sc->sc_bounce_maxblocks; - - DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: nblocks %lu\n", - __func__, nblocks); - - if (bp->bio_cmd == BIO_READ) { - err = ps3disk_read(sc, bp->bio_disk->d_unit, - block, nblocks, data); - } else { - err = ps3disk_write(sc, bp->bio_disk->d_unit, - block, nblocks, data); - } - - if (err) - break; - - block += nblocks; - } + kproc_exit(0); +} - bp->bio_resid = (end - block) * sc->sc_blksize; - if (bp->bio_resid) { - bp->bio_error = EIO; - bp->bio_flags |= BIO_ERROR; - } else { - bp->bio_error = 0; - bp->bio_flags |= BIO_DONE; - } +static void +ps3disk_strategy(struct bio *bp) +{ + struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1; + int err; + + if (sc == NULL) { + bp->bio_flags |= BIO_ERROR; + bp->bio_error = EINVAL; + biodone(bp); + return; + } + + PS3DISK_LOCK(sc); + bp->bio_resid = bp->bio_bcount; + bioq_insert_tail(&sc->sc_bioq, bp); - DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_resid %ld\n", - __func__, bp->bio_resid); + DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_cmd 0x%02x\n", + __func__, bp->bio_cmd); + + err = 0; + if (bp->bio_cmd == BIO_FLUSH) { + bp->bio_driver1 = 0; + err = lv1_storage_send_device_command( + ps3bus_get_device(sc->sc_dev), LV1_STORAGE_ATA_HDDOUT, + 0, 0, 0, 0, (uint64_t *)&bp->bio_driver2); + if (err == LV1_BUSY) + err = EAGAIN; + } else if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { + if (bp->bio_bcount % sc->sc_blksize != 0) { + err = EINVAL; } else { - bp->bio_error = EINVAL; - bp->bio_flags |= BIO_ERROR; + bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT, + (bus_dmamap_t *)(&bp->bio_driver1)); + err = bus_dmamap_load(sc->sc_dmatag, + (bus_dmamap_t)(bp->bio_driver1), bp->bio_data, + bp->bio_bcount, ps3disk_transfer, bp, 0); + if (err == EINPROGRESS) + err = 0; } + } else { + err = EINVAL; + } - if (bp->bio_flags & BIO_ERROR) - disk_err(bp, "hard error", -1, 1); - + if (err == EAGAIN) { + bioq_remove(&sc->sc_bioq, bp); + bioq_insert_tail(&sc->sc_deferredq, bp); + } else if (err != 0) { + bp->bio_error = err; + bp->bio_flags |= BIO_ERROR; + bioq_remove(&sc->sc_bioq, bp); + disk_err(bp, "hard error", -1, 1); biodone(bp); } - PS3DISK_LOCK(sc); - sc->sc_running = -1; - wakeup(sc); PS3DISK_UNLOCK(sc); - - kproc_exit(0); -} - -static int -ps3disk_intr_filter(void *arg) -{ - return (FILTER_SCHEDULE_THREAD); } static void @@ -523,50 +414,55 @@ ps3disk_intr(void *arg) struct ps3disk_softc *sc = (struct ps3disk_softc *) arg; device_t dev = sc->sc_dev; uint64_t devid = ps3bus_get_device(dev); + struct bio *bp; uint64_t tag, status; - int err; + if (lv1_storage_get_async_status(devid, &tag, &status) != 0) + return; + PS3DISK_LOCK(sc); - err = lv1_storage_get_async_status(devid, &tag, &status); - - DPRINTF(sc, PS3DISK_DEBUG_INTR, "%s: err %d tag 0x%016lx status 0x%016lx\n", - __func__, err, tag, status); - - if (err) - goto out; + DPRINTF(sc, PS3DISK_DEBUG_INTR, "%s: tag 0x%016lx " + "status 0x%016lx\n", __func__, tag, status); - if (!sc->sc_bounce_busy) { - device_printf(dev, "Got interrupt while no request pending\n"); - goto out; - } - - if (tag != sc->sc_bounce_tag) - device_printf(dev, "Tag mismatch, got 0x%016lx expected 0x%016lx\n", - tag, sc->sc_bounce_tag); + /* Locate the matching request */ + TAILQ_FOREACH(bp, &sc->sc_bioq.queue, bio_queue) { + if ((uint64_t)bp->bio_driver2 != tag) + continue; - if (status) - device_printf(dev, "Request completed with status 0x%016lx\n", status); + if (status != 0) { + device_printf(sc->sc_dev, "%s error (%#lx)\n", + (bp->bio_cmd == BIO_READ) ? "Read" : "Write", + status); + bp->bio_error = EIO; + bp->bio_flags |= BIO_ERROR; + } else { + bp->bio_error = 0; + bp->bio_resid = 0; + bp->bio_flags |= BIO_DONE; + } - sc->sc_bounce_status = status; - sc->sc_bounce_busy = 0; + if (bp->bio_driver1 != NULL) { + if (bp->bio_cmd == BIO_READ) + bus_dmamap_sync(sc->sc_dmatag, (bus_dmamap_t) + bp->bio_driver1, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t) + bp->bio_driver1); + bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t) + bp->bio_driver1); + } - wakeup(sc); + bioq_remove(&sc->sc_bioq, bp); + biodone(bp); + break; + } -out: + if (bioq_first(&sc->sc_deferredq) != NULL) + wakeup(&sc->sc_deferredq); PS3DISK_UNLOCK(sc); } -static void -ps3disk_getphys(void *arg, bus_dma_segment_t *segs, int nsegs, int error) -{ - if (error != 0) - return; - - *(bus_addr_t *) arg = segs[0].ds_addr; -} - static int ps3disk_get_disk_geometry(struct ps3disk_softc *sc) { @@ -582,8 +478,7 @@ ps3disk_get_disk_geometry(struct ps3disk_softc *sc) lv1_repository_string("blk_size"), 0, &sc->sc_blksize, &junk); if (err) { device_printf(dev, "Could not get block size (0x%08x)\n", err); - err = ENXIO; - goto out; + return (ENXIO); } err = lv1_get_repository_node_value(PS3_LPAR_ID_PME, @@ -591,16 +486,11 @@ ps3disk_get_disk_geometry(struct ps3disk_softc *sc) lv1_repository_string("dev") | dev_index, lv1_repository_string("n_blocks"), 0, &sc->sc_nblocks, &junk); if (err) { - device_printf(dev, "Could not get total number of blocks (0x%08x)\n", - err); + device_printf(dev, "Could not get total number of blocks " + "(0x%08x)\n", err); err = ENXIO; - goto out; } - err = 0; - -out: - return (err); } @@ -655,10 +545,11 @@ ps3disk_enum_regions(struct ps3disk_softc *sc) (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("dev") | dev_index, lv1_repository_string("region") | i, - lv1_repository_string("start"), &sc->sc_reg[i].r_start, &junk); + lv1_repository_string("start"), &sc->sc_reg[i].r_start, + &junk); if (err) { - device_printf(dev, "Could not get region start (0x%08x)\n", - err); + device_printf(dev, "Could not get region start " + "(0x%08x)\n", err); err = ENXIO; goto fail; } @@ -667,16 +558,16 @@ ps3disk_enum_regions(struct ps3disk_softc *sc) (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("dev") | dev_index, lv1_repository_string("region") | i, - lv1_repository_string("size"), &sc->sc_reg[i].r_size, &junk); + lv1_repository_string("size"), &sc->sc_reg[i].r_size, + &junk); if (err) { - device_printf(dev, "Could not get region size (0x%08x)\n", - err); + device_printf(dev, "Could not get region size " + "(0x%08x)\n", err); err = ENXIO; goto fail; } if (i == 0) - /* disables HV access control and grants access to whole disk */ sc->sc_reg[i].r_flags = 0x2; else sc->sc_reg[i].r_flags = 0; @@ -693,160 +584,70 @@ fail: return (err); } -static int -ps3disk_read(struct ps3disk_softc *sc, int regidx, - uint64_t start_sector, uint64_t sector_count, char *data) -{ - device_t dev = sc->sc_dev; - struct ps3disk_region *rp = &sc->sc_reg[regidx]; - uint64_t devid = ps3bus_get_device(dev); - int err; - - PS3DISK_LOCK(sc); - - if (sc->sc_bounce_busy) { - device_printf(dev, "busy\n"); - PS3DISK_UNLOCK(sc); - return EIO; - } - - sc->sc_bounce_busy = 1; - - err = lv1_storage_read(devid, rp->r_id, - start_sector, sector_count, rp->r_flags, - sc->sc_bounce_lpar, &sc->sc_bounce_tag); - if (err) { - device_printf(dev, "Could not read sectors (0x%08x)\n", err); - err = EIO; - goto out; - } - - DPRINTF(sc, PS3DISK_DEBUG_READ, "%s: tag 0x%016lx\n", - __func__, sc->sc_bounce_tag); - - err = msleep(sc, &sc->sc_mtx, PRIBIO, "read", hz); - if (err) { - device_printf(dev, "Read request timed out\n"); - err = EIO; - goto out; - } - - if (sc->sc_bounce_busy || sc->sc_bounce_status) { - err = EIO; - } else { - bus_dmamap_sync(sc->sc_bounce_dmatag, sc->sc_bounce_dmamap, - BUS_DMASYNC_POSTREAD); - memcpy(data, sc->sc_bounce, sector_count * sc->sc_blksize); - err = 0; - } - -out: - - sc->sc_bounce_busy = 0; - - PS3DISK_UNLOCK(sc); - - return (err); -} - -static int -ps3disk_write(struct ps3disk_softc *sc, int regidx, - uint64_t start_sector, uint64_t sector_count, char *data) +static void +ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { - device_t dev = sc->sc_dev; - struct ps3disk_region *rp = &sc->sc_reg[regidx]; - uint64_t devid = ps3bus_get_device(dev); - int err; - - PS3DISK_LOCK(sc); - - if (sc->sc_bounce_busy) { - device_printf(dev, "busy\n"); - PS3DISK_UNLOCK(sc); - return EIO; - } - - memcpy(sc->sc_bounce, data, sector_count * sc->sc_blksize); - - bus_dmamap_sync(sc->sc_bounce_dmatag, sc->sc_bounce_dmamap, - BUS_DMASYNC_PREWRITE); - - sc->sc_bounce_busy = 1; - - err = lv1_storage_write(devid, rp->r_id, - start_sector, sector_count, rp->r_flags, - sc->sc_bounce_lpar, &sc->sc_bounce_tag); - if (err) { - device_printf(dev, "Could not write sectors (0x%08x)\n", err); - err = EIO; - goto out; - } + struct bio *bp = (struct bio *)(arg); + struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1; + struct ps3disk_region *rp = &sc->sc_reg[bp->bio_disk->d_unit]; + uint64_t devid = ps3bus_get_device(sc->sc_dev); + uint64_t block; + int i, err; - DPRINTF(sc, PS3DISK_DEBUG_WRITE, "%s: tag 0x%016lx\n", - __func__, sc->sc_bounce_tag); + /* Locks already held by busdma */ + PS3DISK_ASSERT_LOCKED(sc); - err = msleep(sc, &sc->sc_mtx, PRIBIO, "write", hz); - if (err) { - device_printf(dev, "Write request timed out\n"); - err = EIO; - goto out; + if (error) { + bp->bio_error = error; + bp->bio_flags |= BIO_ERROR; + bioq_remove(&sc->sc_bioq, bp); + biodone(bp); + return; } - err = (sc->sc_bounce_busy || sc->sc_bounce_status) ? EIO : 0; - -out: - - sc->sc_bounce_busy = 0; - - PS3DISK_UNLOCK(sc); - - return (err); -} - -static int -ps3disk_flush(struct ps3disk_softc *sc) -{ - device_t dev = sc->sc_dev; - uint64_t devid = ps3bus_get_device(dev); - int err; - - PS3DISK_LOCK(sc); + block = bp->bio_pblkno; + for (i = 0; i < nsegs; i++) { + KASSERT((segs[i].ds_len % sc->sc_blksize) == 0, + ("DMA fragments not blocksize multiples")); - if (sc->sc_bounce_busy) { - device_printf(dev, "busy\n"); - PS3DISK_UNLOCK(sc); - return EIO; - } - - sc->sc_bounce_busy = 1; + if (bp->bio_cmd == BIO_READ) { + err = lv1_storage_read(devid, rp->r_id, + block, segs[i].ds_len/sc->sc_blksize, + rp->r_flags, segs[i].ds_addr, + (uint64_t *)&bp->bio_driver2); + } else { + bus_dmamap_sync(sc->sc_dmatag, + (bus_dmamap_t)bp->bio_driver1, + BUS_DMASYNC_PREWRITE); + err = lv1_storage_write(devid, rp->r_id, + block, segs[i].ds_len/sc->sc_blksize, + rp->r_flags, segs[i].ds_addr, + (uint64_t *)&bp->bio_driver2); + } - err = lv1_storage_send_device_command(devid, LV1_STORAGE_ATA_HDDOUT, - 0, 0, 0, 0, &sc->sc_bounce_tag); - if (err) { - device_printf(dev, "Could not flush (0x%08x)\n", err); - err = EIO; - goto out; - } + if (err) { + if (err == LV1_BUSY) { + bioq_remove(&sc->sc_bioq, bp); + bioq_insert_tail(&sc->sc_deferredq, bp); + } else { + bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t) + bp->bio_driver1); + bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t) + bp->bio_driver1); + device_printf(sc->sc_dev, "Could not read " + "sectors (0x%08x)\n", err); + bp->bio_error = EINVAL; + bp->bio_flags |= BIO_ERROR; + bioq_remove(&sc->sc_bioq, bp); + biodone(bp); + } - DPRINTF(sc, PS3DISK_DEBUG_FLUSH, "%s: tag 0x%016lx\n", - __func__, sc->sc_bounce_tag); + break; + } - err = msleep(sc, &sc->sc_mtx, PRIBIO, "flush", hz); - if (err) { - device_printf(dev, "Flush request timed out\n"); - err = EIO; - goto out; + DPRINTF(sc, PS3DISK_DEBUG_READ, "%s: tag 0x%016lx\n", + __func__, sc->sc_bounce_tag); } - - err = (sc->sc_bounce_busy || sc->sc_bounce_status) ? EIO : 0; - -out: - - sc->sc_bounce_busy = 0; - - PS3DISK_UNLOCK(sc); - - return (err); } #ifdef PS3DISK_DEBUG -- cgit v1.1 From b51f0413bb9eea9e7f306823369257ccace21801 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 23 Jun 2011 04:06:33 +0000 Subject: Use 4 KB pages for storage bus devices, which seems to be what the HV uses internally. --- sys/powerpc/ps3/ps3bus.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/powerpc/ps3/ps3bus.c b/sys/powerpc/ps3/ps3bus.c index 88b4be2..90f0e87 100644 --- a/sys/powerpc/ps3/ps3bus.c +++ b/sys/powerpc/ps3/ps3bus.c @@ -629,7 +629,7 @@ ps3bus_get_dma_tag(device_t dev, device_t child) { struct ps3bus_devinfo *dinfo = device_get_ivars(child); struct ps3bus_softc *sc = device_get_softc(dev); - int i, err, flags; + int i, err, flags, pagesize; if (dinfo->bustype != PS3_BUSTYPE_SYSBUS && dinfo->bustype != PS3_BUSTYPE_STORAGE) @@ -646,9 +646,13 @@ ps3bus_get_dma_tag(device_t dev, device_t child) dinfo->devtype == PS3_DEVTYPE_USB) flags = 2; /* 8-bit mode */ + pagesize = 24; /* log_2(16 MB) */ + if (dinfo->bustype == PS3_BUSTYPE_STORAGE) + pagesize = 12; /* 4 KB */ + for (i = 0; i < sc->rcount; i++) { err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev, - sc->regions[i].mr_size, 24 /* log_2(16 MB) */, flags, + sc->regions[i].mr_size, pagesize, flags, &dinfo->dma_base[i]); if (err != 0) { device_printf(child, -- cgit v1.1 From 6d4918e45e29c8527fe3383af8f33ef6ed977e35 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 23 Jun 2011 04:35:45 +0000 Subject: Use atomic operations to mask and unmask IRQs. This prevents a problem (obvious in retrospect) in which interrupts on one CPU that are temporarily masked can end up permanently masked when a handler on another CPU clobbers the interrupt mask register with an old copy. --- sys/powerpc/ps3/ps3pic.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sys/powerpc/ps3/ps3pic.c b/sys/powerpc/ps3/ps3pic.c index c00585b..3a62e3c 100644 --- a/sys/powerpc/ps3/ps3pic.c +++ b/sys/powerpc/ps3/ps3pic.c @@ -56,10 +56,10 @@ static void ps3pic_mask(device_t, u_int); static void ps3pic_unmask(device_t, u_int); struct ps3pic_softc { - uint64_t *bitmap_thread0; - uint64_t *mask_thread0; - uint64_t *bitmap_thread1; - uint64_t *mask_thread1; + volatile uint64_t *bitmap_thread0; + volatile uint64_t *mask_thread0; + volatile uint64_t *bitmap_thread1; + volatile uint64_t *mask_thread1; uint64_t sc_ipi_outlet[2]; int sc_vector[64]; @@ -219,8 +219,8 @@ ps3pic_mask(device_t dev, u_int irq) if (irq == sc->sc_ipi_outlet[0]) return; - sc->mask_thread0[0] &= ~(1UL << (63 - irq)); - sc->mask_thread1[0] &= ~(1UL << (63 - irq)); + atomic_clear_64(&sc->mask_thread0[0], 1UL << (63 - irq)); + atomic_clear_64(&sc->mask_thread1[0], 1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); @@ -234,8 +234,8 @@ ps3pic_unmask(device_t dev, u_int irq) uint64_t ppe; sc = device_get_softc(dev); - sc->mask_thread0[0] |= (1UL << (63 - irq)); - sc->mask_thread1[0] |= (1UL << (63 - irq)); + atomic_set_64(&sc->mask_thread0[0], 1UL << (63 - irq)); + atomic_set_64(&sc->mask_thread1[0], 1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); -- cgit v1.1 From e7ea911039376c32826c527f3b67a36fe18f420a Mon Sep 17 00:00:00 2001 From: alc Date: Thu, 23 Jun 2011 05:23:59 +0000 Subject: Revert to using the page queues lock in vm_page_clear_dirty_mask() on MIPS. (At present, although atomic_clear_char() is defined by atomic.h on MIPS, it is not actually implemented by support.S.) --- sys/vm/vm_fault.c | 3 +-- sys/vm/vm_page.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 7568f57..55abe86 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -1095,8 +1095,7 @@ vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, * required in order to call vm_page_dirty(). See * vm_page_clear_dirty_mask(). */ -#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) || \ - defined(__mips__) +#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) vm_page_dirty(*mp); #else vm_page_lock_queues(); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 033c4c9..8e0c8bb 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -2336,8 +2336,7 @@ vm_page_clear_dirty_mask(vm_page_t m, int pagebits) if ((m->oflags & VPO_BUSY) == 0 && (m->flags & PG_WRITEABLE) == 0) m->dirty &= ~pagebits; else { -#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) || \ - defined(__mips__) +#if defined(__amd64__) || defined(__i386__) || defined(__ia64__) /* * On the aforementioned architectures, the page queues lock * is not required by the following read-modify-write -- cgit v1.1 From 65bbe8b4728cec874007cf3b252103f6641d694b Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 23 Jun 2011 06:53:13 +0000 Subject: Fix indenting issues introduced by the previous commit. --- sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c | 4 ++-- sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c index 6c1937a..bf0b38a 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c @@ -84,9 +84,9 @@ ar5212BeaconInit(struct ath_hal *ah, case HAL_M_HOSTAP: case HAL_M_IBSS: bt.bt_nextdba = (next_beacon - - ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ break; } /* diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c index ee6c1eb..66b5053 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c @@ -93,9 +93,9 @@ ar5416BeaconInit(struct ath_hal *ah, /* fall thru... */ case HAL_M_HOSTAP: bt.bt_nextdba = (next_beacon - - ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_dma_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_nextswba = (next_beacon - - ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ + ah->ah_config.ah_sw_beacon_response_time) << 3; /* 1/8 TU */ bt.bt_flags |= AR_TIMER_MODE_TBTT | AR_TIMER_MODE_DBA | AR_TIMER_MODE_SWBA; -- cgit v1.1 From d00135573a2cb956464d92b084d1337dd4be1910 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 23 Jun 2011 06:55:29 +0000 Subject: Re-introduce a global ath_hal_debug again for now, whilst I figure out what to do about the few cases where the HAL state isn't available (regdomain) or isn't yet setup (probe/attach.) The global ath_hal_debug now affects all instances of the HAL. This also restores the ability for probe/attach debugging to work; as the sysctl tree may not be attached at that point. Users can just set the global "hw.ath.hal.debug" to a suitable value to enable probe/attach related debugging. --- sys/dev/ath/ath_hal/ah_internal.h | 21 ++++++++++++++++++++- sys/dev/ath/ath_hal/ah_regdomain.c | 4 ++-- sys/dev/ath/ath_hal/ar5210/ar5210_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar5211/ar5211_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar5212/ar5112.c | 2 +- sys/dev/ath/ath_hal/ar5212/ar5212_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar5312/ar5312_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar9001/ar9130_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar9001/ar9160_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar9002/ar9280_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar9002/ar9285_attach.c | 4 ++-- sys/dev/ath/ath_hal/ar9002/ar9287_attach.c | 4 ++-- 13 files changed, 43 insertions(+), 24 deletions(-) diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h index 91edc34..0959218 100644 --- a/sys/dev/ath/ath_hal/ah_internal.h +++ b/sys/dev/ath/ath_hal/ah_internal.h @@ -498,10 +498,29 @@ extern void ath_hal_free(void *); /* common debugging interfaces */ #ifdef AH_DEBUG #include "ah_debug.h" +extern int ath_hal_debug; /* Global debug flags */ + +/* + * This is used for global debugging, when ahp doesn't yet have the + * related debugging state. For example, during probe/attach. + */ +#define HALDEBUG_G(_ah, __m, ...) \ + do { \ + if ((__m) == HAL_DEBUG_UNMASKABLE || \ + ath_hal_debug & (__m)) { \ + DO_HALDEBUG((_ah), (__m), __VA_ARGS__); \ + } \ + } while (0); + +/* + * This is used for local debugging, when ahp isn't NULL and + * thus may have debug flags set. + */ #define HALDEBUG(_ah, __m, ...) \ do { \ if ((__m) == HAL_DEBUG_UNMASKABLE || \ - ((_ah != AH_NULL) && (((struct ath_hal*)_ah)->ah_config.ah_debug & (__m)))) { \ + ath_hal_debug & (__m) || \ + (_ah)->ah_config.ah_debug & (__m)) { \ DO_HALDEBUG((_ah), (__m), __VA_ARGS__); \ } \ } while(0); diff --git a/sys/dev/ath/ath_hal/ah_regdomain.c b/sys/dev/ath/ath_hal/ah_regdomain.c index c17d0f6..9aae332 100644 --- a/sys/dev/ath/ath_hal/ah_regdomain.c +++ b/sys/dev/ath/ath_hal/ah_regdomain.c @@ -167,7 +167,7 @@ isEepromValid(struct ath_hal *ah) if (regDomainPairs[i].regDmnEnum == rd) return AH_TRUE; } - HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, + HALDEBUG_G(ah, HAL_DEBUG_REGDOMAIN, "%s: invalid regulatory domain/country code 0x%x\n", __func__, rd); return AH_FALSE; } @@ -609,7 +609,7 @@ ath_hal_mapgsm(int sku, int freq) return 1544 + freq; if (sku == SKU_SR9) return 3344 - freq; - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot map freq %u unknown gsm sku %u\n", __func__, freq, sku); return freq; diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c index 2068733..41d957a 100644 --- a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c +++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c @@ -181,14 +181,14 @@ ar5210Attach(uint16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS ecode; int i; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: devid 0x%x sc %p st %p sh %p\n", __func__, devid, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5210)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: no memory for state block\n", __func__); ecode = HAL_ENOMEM; goto bad; diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c index 308ecc9..14daa0b 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c @@ -200,13 +200,13 @@ ar5211Attach(uint16_t devid, HAL_SOFTC sc, uint16_t eeval; HAL_STATUS ecode; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5211)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); ecode = HAL_ENOMEM; goto bad; diff --git a/sys/dev/ath/ath_hal/ar5212/ar5112.c b/sys/dev/ath/ath_hal/ar5212/ar5112.c index c1920b9..1003068 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5112.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5112.c @@ -611,7 +611,7 @@ getFullPwrTable(uint16_t numPcdacs, uint16_t *pcdacs, int16_t *power, int16_t ma uint16_t idxR = 1; if (numPcdacs < 2) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: at least 2 pcdac values needed [%d]\n", __func__, numPcdacs); return AH_FALSE; diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c index 8e7f3cb..01c0e2c 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c @@ -317,13 +317,13 @@ ar5212Attach(uint16_t devid, HAL_SOFTC sc, uint16_t eeval; HAL_STATUS ecode; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c index 4ca1a4d..d1689d5 100644 --- a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c +++ b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c @@ -71,13 +71,13 @@ ar5312Attach(uint16_t devid, HAL_SOFTC sc, uint16_t eeval; HAL_STATUS ecode; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, st, (void*) sh); /* NB: memory is returned zero'd */ ahp = ath_hal_malloc(sizeof (struct ath_hal_5212)); if (ahp == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index e636325..607f97a 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -241,7 +241,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, HAL_STATUS ecode; HAL_BOOL rfStatus; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ @@ -250,7 +250,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc, sizeof(ar5416Addac) ); if (ahp5416 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c index 2a3f3f0..518ed85 100644 --- a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c +++ b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c @@ -78,13 +78,13 @@ ar9130Attach(uint16_t devid, HAL_SOFTC sc, HAL_STATUS ecode; HAL_BOOL rfStatus; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); if (ahp5416 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c index 44a549d..a87d1ad 100644 --- a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c +++ b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c @@ -101,13 +101,13 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc, HAL_STATUS ecode; HAL_BOOL rfStatus; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp5416 = ath_hal_malloc(sizeof (struct ath_hal_5416)); if (ahp5416 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c index ebe3be1..3743c21 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c @@ -120,13 +120,13 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc, int8_t pwr_table_offset; uint8_t pwr; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp9280 = ath_hal_malloc(sizeof (struct ath_hal_9280)); if (ahp9280 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c index 9120313..2547148 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c @@ -118,13 +118,13 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc, HAL_STATUS ecode; HAL_BOOL rfStatus; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285)); if (ahp9285 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c index 9cbe0a5..f3b403b 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c @@ -119,13 +119,13 @@ ar9287Attach(uint16_t devid, HAL_SOFTC sc, HAL_BOOL rfStatus; int8_t pwr_table_offset; - HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", + HALDEBUG_G(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n", __func__, sc, (void*) st, (void*) sh); /* NB: memory is returned zero'd */ ahp9287 = ath_hal_malloc(sizeof (struct ath_hal_9287)); if (ahp9287 == AH_NULL) { - HALDEBUG(AH_NULL, HAL_DEBUG_ANY, + HALDEBUG_G(AH_NULL, HAL_DEBUG_ANY, "%s: cannot allocate memory for state block\n", __func__); *status = HAL_ENOMEM; return AH_NULL; -- cgit v1.1 From d0f827f1f21ae29da0f452fc6eade31c47818b46 Mon Sep 17 00:00:00 2001 From: hselasky Date: Thu, 23 Jun 2011 07:54:03 +0000 Subject: - Add more USB templates for various USB device classes - Add basic template support for USB 3.0 - Export definition of template sysctl numbers through usb_ioctl.h MFC after: 7 days --- sys/conf/files | 6 +- sys/dev/usb/template/usb_template.c | 48 +++- sys/dev/usb/template/usb_template.h | 14 +- sys/dev/usb/template/usb_template_audio.c | 400 ++++++++++++++++++++++++++++++ sys/dev/usb/template/usb_template_cdce.c | 2 +- sys/dev/usb/template/usb_template_kbd.c | 222 +++++++++++++++++ sys/dev/usb/template/usb_template_modem.c | 252 +++++++++++++++++++ sys/dev/usb/template/usb_template_mouse.c | 220 ++++++++++++++++ sys/dev/usb/template/usb_template_msc.c | 4 +- sys/dev/usb/template/usb_template_mtp.c | 4 +- sys/dev/usb/usb_ioctl.h | 14 ++ sys/modules/usb/template/Makefile | 9 +- 12 files changed, 1182 insertions(+), 13 deletions(-) create mode 100644 sys/dev/usb/template/usb_template_audio.c create mode 100644 sys/dev/usb/template/usb_template_kbd.c create mode 100644 sys/dev/usb/template/usb_template_modem.c create mode 100644 sys/dev/usb/template/usb_template_mouse.c diff --git a/sys/conf/files b/sys/conf/files index a62e1a6..1a8d5ff 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1991,8 +1991,12 @@ dev/usb/quirk/usb_quirk.c optional usb # # USB templates # -dev/usb/template/usb_template.c optional usb_template +dev/usb/template/usb_template.c optional usb_template +dev/usb/template/usb_template_audio.c optional usb_template dev/usb/template/usb_template_cdce.c optional usb_template +dev/usb/template/usb_template_kbd.c optional usb_template +dev/usb/template/usb_template_modem.c optional usb_template +dev/usb/template/usb_template_mouse.c optional usb_template dev/usb/template/usb_template_msc.c optional usb_template dev/usb/template/usb_template_mtp.c optional usb_template # diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c index 7bf17fe..cf97482 100644 --- a/sys/dev/usb/template/usb_template.c +++ b/sys/dev/usb/template/usb_template.c @@ -49,6 +49,7 @@ #include #include +#include #include #include #include "usbdevs.h" @@ -141,6 +142,31 @@ usb_make_raw_desc(struct usb_temp_setup *temp, ud->bSlaveInterface[0] += temp->bInterfaceNumber; } + + /* check if we have got an interface association descriptor */ + + if ((raw[0] >= sizeof(struct usb_interface_assoc_descriptor)) && + (raw[1] == UDESC_IFACE_ASSOC)) { + struct usb_interface_assoc_descriptor *iad = (void *)dst; + + /* update the interface number */ + + iad->bFirstInterface += + temp->bInterfaceNumber; + } + + /* check if we have got a call management descriptor */ + + if ((raw[0] >= sizeof(struct usb_cdc_cm_descriptor)) && + (raw[1] == UDESC_CS_INTERFACE) && + (raw[2] == UDESCSUB_CDC_CM)) { + struct usb_cdc_cm_descriptor *ccd = (void *)dst; + + /* update the interface number */ + + ccd->bDataInterface += + temp->bInterfaceNumber; + } } temp->size += len; } @@ -476,6 +502,10 @@ usb_make_device_desc(struct usb_temp_setup *temp, USETW(utd->udd.bcdUSB, 0x0250); utd->udd.bMaxPacketSize = 255; /* 512 bytes */ break; + case USB_SPEED_SUPER: + USETW(utd->udd.bcdUSB, 0x0300); + utd->udd.bMaxPacketSize = 9; /* 2**9 = 512 bytes */ + break; default: temp->err = USB_ERR_INVAL; break; @@ -1303,15 +1333,27 @@ usb_temp_setup_by_index(struct usb_device *udev, uint16_t index) usb_error_t err; switch (index) { - case 0: + case USB_TEMP_MSC: err = usb_temp_setup(udev, &usb_template_msc); break; - case 1: + case USB_TEMP_CDCE: err = usb_temp_setup(udev, &usb_template_cdce); break; - case 2: + case USB_TEMP_MTP: err = usb_temp_setup(udev, &usb_template_mtp); break; + case USB_TEMP_MODEM: + err = usb_temp_setup(udev, &usb_template_modem); + break; + case USB_TEMP_AUDIO: + err = usb_temp_setup(udev, &usb_template_audio); + break; + case USB_TEMP_KBD: + err = usb_temp_setup(udev, &usb_template_kbd); + break; + case USB_TEMP_MOUSE: + err = usb_temp_setup(udev, &usb_template_mouse); + break; default: return (USB_ERR_INVAL); } diff --git a/sys/dev/usb/template/usb_template.h b/sys/dev/usb/template/usb_template.h index 2473af3..b05272f 100644 --- a/sys/dev/usb/template/usb_template.h +++ b/sys/dev/usb/template/usb_template.h @@ -30,6 +30,10 @@ #ifndef _USB_TEMPLATE_H_ #define _USB_TEMPLATE_H_ +#ifndef USB_TEMPLATE_VENDOR +#define USB_TEMPLATE_VENDOR 0x0001 +#endif + typedef const void *(usb_temp_get_string_desc_t)(uint16_t lang_id, uint8_t string_index); typedef const void *(usb_temp_get_vendor_desc_t)(const struct usb_device_request *req, uint16_t *plen); @@ -94,10 +98,14 @@ struct usb_temp_data { /* prototypes */ +extern const struct usb_temp_device_desc usb_template_audio; extern const struct usb_temp_device_desc usb_template_cdce; -extern const struct usb_temp_device_desc usb_template_msc; /* Mass Storage Class */ -extern const struct usb_temp_device_desc usb_template_mtp; /* Message Transfer - * Protocol */ +extern const struct usb_temp_device_desc usb_template_kbd; +extern const struct usb_temp_device_desc usb_template_modem; +extern const struct usb_temp_device_desc usb_template_mouse; +extern const struct usb_temp_device_desc usb_template_msc; +extern const struct usb_temp_device_desc usb_template_mtp; + usb_error_t usb_temp_setup(struct usb_device *, const struct usb_temp_device_desc *); void usb_temp_unsetup(struct usb_device *); diff --git a/sys/dev/usb/template/usb_template_audio.c b/sys/dev/usb/template/usb_template_audio.c new file mode 100644 index 0000000..1e2e568 --- /dev/null +++ b/sys/dev/usb/template/usb_template_audio.c @@ -0,0 +1,400 @@ +#include +__FBSDID("$FreeBSD$"); + +/*- + * Copyright (c) 2010 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * This file contains the USB template for an USB Audio Device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +enum { + INDEX_AUDIO_LANG, + INDEX_AUDIO_MIXER, + INDEX_AUDIO_RECORD, + INDEX_AUDIO_PLAYBACK, + INDEX_AUDIO_PRODUCT, + INDEX_AUDIO_MAX, +}; + +#define STRING_LANG \ + 0x09, 0x04, /* American English */ + +#define STRING_AUDIO_PRODUCT \ + 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, \ + 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \ + 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0, + +#define STRING_AUDIO_MIXER \ + 'M', 0, 'i', 0, 'x', 0, 'e', 0, 'r', 0, ' ', 0, \ + 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, + +#define STRING_AUDIO_RECORD \ + 'R', 0, 'e', 0, 'c', 0, 'o', 0, 'r', 0, 'd', 0, ' ', 0, \ + 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, + +#define STRING_AUDIO_PLAYBACK \ + 'P', 0, 'l', 0, 'a', 0, 'y', 0, 'b', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, \ + 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, + + +/* make the real string descriptors */ + +USB_MAKE_STRING_DESC(STRING_LANG, string_lang); +USB_MAKE_STRING_DESC(STRING_AUDIO_MIXER, string_audio_mixer); +USB_MAKE_STRING_DESC(STRING_AUDIO_RECORD, string_audio_record); +USB_MAKE_STRING_DESC(STRING_AUDIO_PLAYBACK, string_audio_playback); +USB_MAKE_STRING_DESC(STRING_AUDIO_PRODUCT, string_audio_product); + +/* prototypes */ + +/* Audio Mixer description structures */ + +static const uint8_t audio_raw_desc_0[] = { + 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02, + 0x01, 0x02 +}; + +static const uint8_t audio_raw_desc_1[] = { + 0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, + 0x03, 0x00, 0x00, 0x00 +}; + +static const uint8_t audio_raw_desc_2[] = { + 0x0c, 0x24, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, + 0x03, 0x00, 0x00, 0x00 +}; + +static const uint8_t audio_raw_desc_3[] = { + 0x0c, 0x24, 0x02, 0x03, 0x03, 0x06, 0x00, 0x02, + 0x03, 0x00, 0x00, 0x00 +}; + +static const uint8_t audio_raw_desc_4[] = { + 0x0c, 0x24, 0x02, 0x04, 0x05, 0x06, 0x00, 0x02, + 0x03, 0x00, 0x00, 0x00 +}; + +static const uint8_t audio_raw_desc_5[] = { + 0x09, 0x24, 0x03, 0x05, 0x05, 0x06, 0x00, 0x01, + 0x00 +}; + +static const uint8_t audio_raw_desc_6[] = { + 0x09, 0x24, 0x03, 0x06, 0x01, 0x03, 0x00, 0x09, + 0x00 +}; + +static const uint8_t audio_raw_desc_7[] = { + 0x09, 0x24, 0x03, 0x07, 0x01, 0x01, 0x00, 0x08, + 0x00 +}; + +static const uint8_t audio_raw_desc_8[] = { + 0x09, 0x24, 0x05, 0x08, 0x03, 0x0a, 0x0b, 0x0c, + 0x00 +}; + +static const uint8_t audio_raw_desc_9[] = { + 0x0a, 0x24, 0x06, 0x09, 0x0f, 0x01, 0x01, 0x02, + 0x02, 0x00 +}; + +static const uint8_t audio_raw_desc_10[] = { + 0x0a, 0x24, 0x06, 0x0a, 0x02, 0x01, 0x43, 0x00, + 0x00, 0x00 +}; + +static const uint8_t audio_raw_desc_11[] = { + 0x0a, 0x24, 0x06, 0x0b, 0x03, 0x01, 0x01, 0x02, + 0x02, 0x00 +}; + +static const uint8_t audio_raw_desc_12[] = { + 0x0a, 0x24, 0x06, 0x0c, 0x04, 0x01, 0x01, 0x00, + 0x00, 0x00 +}; + +static const uint8_t audio_raw_desc_13[] = { + 0x0a, 0x24, 0x06, 0x0d, 0x02, 0x01, 0x03, 0x00, + 0x00, 0x00 +}; + +static const uint8_t audio_raw_desc_14[] = { + 0x0a, 0x24, 0x06, 0x0e, 0x03, 0x01, 0x01, 0x02, + 0x02, 0x00 +}; + +static const uint8_t audio_raw_desc_15[] = { + 0x0f, 0x24, 0x04, 0x0f, 0x03, 0x01, 0x0d, 0x0e, + 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const void *audio_raw_iface_0_desc[] = { + audio_raw_desc_0, + audio_raw_desc_1, + audio_raw_desc_2, + audio_raw_desc_3, + audio_raw_desc_4, + audio_raw_desc_5, + audio_raw_desc_6, + audio_raw_desc_7, + audio_raw_desc_8, + audio_raw_desc_9, + audio_raw_desc_10, + audio_raw_desc_11, + audio_raw_desc_12, + audio_raw_desc_13, + audio_raw_desc_14, + audio_raw_desc_15, + NULL, +}; + +static const struct usb_temp_interface_desc audio_iface_0 = { + .ppEndpoints = NULL, /* no endpoints */ + .ppRawDesc = audio_raw_iface_0_desc, + .bInterfaceClass = 1, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .iInterface = INDEX_AUDIO_MIXER, +}; + +static const uint8_t audio_raw_desc_20[] = { + 0x07, 0x24, 0x01, 0x01, 0x03, 0x01, 0x00 + +}; + +static const uint8_t audio_raw_desc_21[] = { + 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, + /* 48kHz */ + 0x80, 0xbb, 0x00 +}; + +static const uint8_t audio_raw_desc_22[] = { + 0x07, 0x25, 0x01, 0x00, 0x01, 0x04, 0x00 +}; + +static const void *audio_raw_iface_1_desc[] = { + audio_raw_desc_20, + audio_raw_desc_21, + NULL, +}; + +static const void *audio_raw_ep_1_desc[] = { + audio_raw_desc_22, + NULL, +}; + +static const struct usb_temp_packet_size audio_isoc_mps = { + .mps[USB_SPEED_FULL] = 0xC8, + .mps[USB_SPEED_HIGH] = 0xC8, +}; + +static const struct usb_temp_interval audio_isoc_interval = { + .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */ + .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */ +}; + +static const struct usb_temp_endpoint_desc audio_isoc_out_ep = { + .ppRawDesc = audio_raw_ep_1_desc, + .pPacketSize = &audio_isoc_mps, + .pIntervals = &audio_isoc_interval, + .bEndpointAddress = UE_DIR_OUT, + .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, +}; + +static const struct usb_temp_endpoint_desc *audio_iface_1_ep[] = { + &audio_isoc_out_ep, + NULL, +}; + +static const struct usb_temp_interface_desc audio_iface_1_alt_0 = { + .ppEndpoints = NULL, /* no endpoints */ + .ppRawDesc = NULL, /* no raw descriptors */ + .bInterfaceClass = 1, + .bInterfaceSubClass = 2, + .bInterfaceProtocol = 0, + .iInterface = INDEX_AUDIO_PLAYBACK, +}; + +static const struct usb_temp_interface_desc audio_iface_1_alt_1 = { + .ppEndpoints = audio_iface_1_ep, + .ppRawDesc = audio_raw_iface_1_desc, + .bInterfaceClass = 1, + .bInterfaceSubClass = 2, + .bInterfaceProtocol = 0, + .iInterface = INDEX_AUDIO_PLAYBACK, + .isAltInterface = 1, /* this is an alternate setting */ +}; + +static const uint8_t audio_raw_desc_30[] = { + 0x07, 0x24, 0x01, 0x07, 0x01, 0x01, 0x00 + +}; + +static const uint8_t audio_raw_desc_31[] = { + 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, + /* 48kHz */ + 0x80, 0xbb, 0x00 +}; + +static const uint8_t audio_raw_desc_32[] = { + 0x07, 0x25, 0x01, 0x01, 0x00, 0x00, 0x00 +}; + +static const void *audio_raw_iface_2_desc[] = { + audio_raw_desc_30, + audio_raw_desc_31, + NULL, +}; + +static const void *audio_raw_ep_2_desc[] = { + audio_raw_desc_32, + NULL, +}; + +static const struct usb_temp_endpoint_desc audio_isoc_in_ep = { + .ppRawDesc = audio_raw_ep_2_desc, + .pPacketSize = &audio_isoc_mps, + .pIntervals = &audio_isoc_interval, + .bEndpointAddress = UE_DIR_IN, + .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, +}; + +static const struct usb_temp_endpoint_desc *audio_iface_2_ep[] = { + &audio_isoc_in_ep, + NULL, +}; + +static const struct usb_temp_interface_desc audio_iface_2_alt_0 = { + .ppEndpoints = NULL, /* no endpoints */ + .ppRawDesc = NULL, /* no raw descriptors */ + .bInterfaceClass = 1, + .bInterfaceSubClass = 2, + .bInterfaceProtocol = 0, + .iInterface = INDEX_AUDIO_RECORD, +}; + +static const struct usb_temp_interface_desc audio_iface_2_alt_1 = { + .ppEndpoints = audio_iface_2_ep, + .ppRawDesc = audio_raw_iface_2_desc, + .bInterfaceClass = 1, + .bInterfaceSubClass = 2, + .bInterfaceProtocol = 0, + .iInterface = INDEX_AUDIO_RECORD, + .isAltInterface = 1, /* this is an alternate setting */ +}; + +static const struct usb_temp_interface_desc *audio_interfaces[] = { + &audio_iface_0, + &audio_iface_1_alt_0, + &audio_iface_1_alt_1, + &audio_iface_2_alt_0, + &audio_iface_2_alt_1, + NULL, +}; + +static const struct usb_temp_config_desc audio_config_desc = { + .ppIfaceDesc = audio_interfaces, + .bmAttributes = UC_BUS_POWERED, + .bMaxPower = 25, /* 50 mA */ + .iConfiguration = INDEX_AUDIO_PRODUCT, +}; + +static const struct usb_temp_config_desc *audio_configs[] = { + &audio_config_desc, + NULL, +}; + +static usb_temp_get_string_desc_t audio_get_string_desc; + +const struct usb_temp_device_desc usb_template_audio = { + .getStringDesc = &audio_get_string_desc, + .ppConfigDesc = audio_configs, + .idVendor = USB_TEMPLATE_VENDOR, + .idProduct = 0x000A, + .bcdDevice = 0x0100, + .bDeviceClass = UDCLASS_COMM, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .iManufacturer = 0, + .iProduct = INDEX_AUDIO_PRODUCT, + .iSerialNumber = 0, +}; + +/*------------------------------------------------------------------------* + * audio_get_string_desc + * + * Return values: + * NULL: Failure. No such string. + * Else: Success. Pointer to string descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +audio_get_string_desc(uint16_t lang_id, uint8_t string_index) +{ + static const void *ptr[INDEX_AUDIO_MAX] = { + [INDEX_AUDIO_LANG] = &string_lang, + [INDEX_AUDIO_MIXER] = &string_audio_mixer, + [INDEX_AUDIO_RECORD] = &string_audio_record, + [INDEX_AUDIO_PLAYBACK] = &string_audio_playback, + [INDEX_AUDIO_PRODUCT] = &string_audio_product, + }; + + if (string_index == 0) { + return (&string_lang); + } + if (lang_id != 0x0409) { + return (NULL); + } + if (string_index < INDEX_AUDIO_MAX) { + return (ptr[string_index]); + } + return (NULL); +} diff --git a/sys/dev/usb/template/usb_template_cdce.c b/sys/dev/usb/template/usb_template_cdce.c index c8b2c6c..481a69c 100644 --- a/sys/dev/usb/template/usb_template_cdce.c +++ b/sys/dev/usb/template/usb_template_cdce.c @@ -264,7 +264,7 @@ static const struct usb_temp_config_desc *eth_configs[] = { const struct usb_temp_device_desc usb_template_cdce = { .getStringDesc = ð_get_string_desc, .ppConfigDesc = eth_configs, - .idVendor = 0x0001, + .idVendor = USB_TEMPLATE_VENDOR, .idProduct = 0x0001, .bcdDevice = 0x0100, .bDeviceClass = UDCLASS_COMM, diff --git a/sys/dev/usb/template/usb_template_kbd.c b/sys/dev/usb/template/usb_template_kbd.c new file mode 100644 index 0000000..4a9b9da --- /dev/null +++ b/sys/dev/usb/template/usb_template_kbd.c @@ -0,0 +1,222 @@ +#include +__FBSDID("$FreeBSD$"); + +/*- + * Copyright (c) 2010 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * This file contains the USB template for an USB Keyboard Device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +enum { + INDEX_LANG, + INDEX_KEYBOARD, + INDEX_PRODUCT, + INDEX_MAX, +}; + +#define STRING_LANG \ + 0x09, 0x04, /* American English */ + +#define STRING_PRODUCT \ + 'K', 0, 'e', 0, 'y', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0, \ + 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \ + 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0, + +#define STRING_KEYBOARD \ + 'K', 0, 'e', 0, 'y', 0, 'b', 0, 'o', 0, 'a', 0, 'r', 0, 'd', 0, ' ', 0, \ + 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, + +/* make the real string descriptors */ + +USB_MAKE_STRING_DESC(STRING_LANG, string_lang); +USB_MAKE_STRING_DESC(STRING_KEYBOARD, string_keyboard); +USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product); + +/* prototypes */ + +static const struct usb_temp_packet_size keyboard_intr_mps = { + .mps[USB_SPEED_LOW] = 16, + .mps[USB_SPEED_FULL] = 16, + .mps[USB_SPEED_HIGH] = 16, +}; + +static const struct usb_temp_interval keyboard_intr_interval = { + .bInterval[USB_SPEED_LOW] = 2, /* ms */ + .bInterval[USB_SPEED_FULL] = 2, + .bInterval[USB_SPEED_HIGH] = 2 * 8, +}; + +static uint8_t keyboard_hid_descriptor[] = { + 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, + 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, + 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, + 0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 0x75, 0x01, + 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, 0x02, + 0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06, + 0x75, 0x08, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05, + 0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00, + 0xc0 +}; + +static const struct usb_temp_endpoint_desc keyboard_ep_0 = { + .ppRawDesc = NULL, /* no raw descriptors */ + .pPacketSize = &keyboard_intr_mps, + .pIntervals = &keyboard_intr_interval, + .bEndpointAddress = UE_DIR_IN, + .bmAttributes = UE_INTERRUPT, +}; + +static const struct usb_temp_endpoint_desc *keyboard_endpoints[] = { + &keyboard_ep_0, + NULL, +}; + +static const uint8_t keyboard_raw_desc[] = { + 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(keyboard_hid_descriptor), + 0x00 +}; + +static const void *keyboard_iface_0_desc[] = { + keyboard_raw_desc, + NULL, +}; + +static const struct usb_temp_interface_desc keyboard_iface_0 = { + .ppRawDesc = keyboard_iface_0_desc, + .ppEndpoints = keyboard_endpoints, + .bInterfaceClass = 3, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = INDEX_KEYBOARD, +}; + +static const struct usb_temp_interface_desc *keyboard_interfaces[] = { + &keyboard_iface_0, + NULL, +}; + +static const struct usb_temp_config_desc keyboard_config_desc = { + .ppIfaceDesc = keyboard_interfaces, + .bmAttributes = UC_BUS_POWERED, + .bMaxPower = 25, /* 50 mA */ + .iConfiguration = INDEX_PRODUCT, +}; + +static const struct usb_temp_config_desc *keyboard_configs[] = { + &keyboard_config_desc, + NULL, +}; + +static usb_temp_get_string_desc_t keyboard_get_string_desc; +static usb_temp_get_vendor_desc_t keyboard_get_vendor_desc; + +const struct usb_temp_device_desc usb_template_kbd = { + .getStringDesc = &keyboard_get_string_desc, + .getVendorDesc = &keyboard_get_vendor_desc, + .ppConfigDesc = keyboard_configs, + .idVendor = USB_TEMPLATE_VENDOR, + .idProduct = 0x00CB, + .bcdDevice = 0x0100, + .bDeviceClass = UDCLASS_COMM, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .iManufacturer = 0, + .iProduct = INDEX_PRODUCT, + .iSerialNumber = 0, +}; + +/*------------------------------------------------------------------------* + * keyboard_get_vendor_desc + * + * Return values: + * NULL: Failure. No such vendor descriptor. + * Else: Success. Pointer to vendor descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +keyboard_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen) +{ + if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) && + (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) && + (req->wIndex[1] == 0) && (req->wIndex[0] == 0)) { + + *plen = sizeof(keyboard_hid_descriptor); + return (keyboard_hid_descriptor); + } + return (NULL); +} + +/*------------------------------------------------------------------------* + * keyboard_get_string_desc + * + * Return values: + * NULL: Failure. No such string. + * Else: Success. Pointer to string descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +keyboard_get_string_desc(uint16_t lang_id, uint8_t string_index) +{ + static const void *ptr[INDEX_MAX] = { + [INDEX_LANG] = &string_lang, + [INDEX_KEYBOARD] = &string_keyboard, + [INDEX_PRODUCT] = &string_product, + }; + + if (string_index == 0) { + return (&string_lang); + } + if (lang_id != 0x0409) { + return (NULL); + } + if (string_index < INDEX_MAX) { + return (ptr[string_index]); + } + return (NULL); +} diff --git a/sys/dev/usb/template/usb_template_modem.c b/sys/dev/usb/template/usb_template_modem.c new file mode 100644 index 0000000..6e0f940 --- /dev/null +++ b/sys/dev/usb/template/usb_template_modem.c @@ -0,0 +1,252 @@ +#include +__FBSDID("$FreeBSD$"); + +/*- + * Copyright (c) 2010 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * This file contains the USB template for an USB Modem Device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +enum { + INDEX_LANG, + INDEX_MODEM, + INDEX_PRODUCT, + INDEX_MAX, +}; + +#define STRING_LANG \ + 0x09, 0x04, /* American English */ + +#define STRING_PRODUCT \ + 'M', 0, 'o', 0, 'd', 0, 'e', 0, 'm', 0, ' ', 0, \ + 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \ + 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, ' ', 0, + +#define STRING_MODEM \ + 'M', 0, 'o', 0, 'd', 0, 'e', 0, 'm', 0, ' ', 0, \ + 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, + +/* make the real string descriptors */ + +USB_MAKE_STRING_DESC(STRING_LANG, string_lang); +USB_MAKE_STRING_DESC(STRING_MODEM, string_modem); +USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product); + +#define MODEM_IFACE_0 0 +#define MODEM_IFACE_1 1 + +/* prototypes */ + +static const struct usb_temp_packet_size modem_bulk_mps = { + .mps[USB_SPEED_LOW] = 8, + .mps[USB_SPEED_FULL] = 64, + .mps[USB_SPEED_HIGH] = 512, +}; + +static const struct usb_temp_packet_size modem_intr_mps = { + .mps[USB_SPEED_LOW] = 8, + .mps[USB_SPEED_FULL] = 8, + .mps[USB_SPEED_HIGH] = 8, +}; + +static const struct usb_temp_interval modem_intr_interval = { + .bInterval[USB_SPEED_LOW] = 10, + .bInterval[USB_SPEED_FULL] = 10, + .bInterval[USB_SPEED_HIGH] = 10 * 8, +}; + +static const struct usb_temp_endpoint_desc modem_ep_0 = { + .pPacketSize = &modem_intr_mps, + .pIntervals = &modem_intr_interval, + .bEndpointAddress = UE_DIR_IN, + .bmAttributes = UE_INTERRUPT, +}; + +static const struct usb_temp_endpoint_desc modem_ep_1 = { + .pPacketSize = &modem_bulk_mps, + .bEndpointAddress = UE_DIR_OUT, + .bmAttributes = UE_BULK, +}; + +static const struct usb_temp_endpoint_desc modem_ep_2 = { + .pPacketSize = &modem_bulk_mps, + .bEndpointAddress = UE_DIR_IN, + .bmAttributes = UE_BULK, +}; + +static const struct usb_temp_endpoint_desc *modem_iface_0_ep[] = { + &modem_ep_0, + NULL, +}; + +static const struct usb_temp_endpoint_desc *modem_iface_1_ep[] = { + &modem_ep_1, + &modem_ep_2, + NULL, +}; + +static const uint8_t modem_raw_desc_0[] = { + 0x05, 0x24, 0x00, 0x10, 0x01 +}; + +static const uint8_t modem_raw_desc_1[] = { + 0x05, 0x24, 0x06, MODEM_IFACE_0, MODEM_IFACE_1 +}; + +static const uint8_t modem_raw_desc_2[] = { + 0x05, 0x24, 0x01, 0x03, MODEM_IFACE_1 +}; + +static const uint8_t modem_raw_desc_3[] = { + 0x04, 0x24, 0x02, 0x07 +}; + +static const void *modem_iface_0_desc[] = { + &modem_raw_desc_0, + &modem_raw_desc_1, + &modem_raw_desc_2, + &modem_raw_desc_3, + NULL, +}; + +static const struct usb_temp_interface_desc modem_iface_0 = { + .ppRawDesc = modem_iface_0_desc, + .ppEndpoints = modem_iface_0_ep, + .bInterfaceClass = 2, + .bInterfaceSubClass = 2, + .bInterfaceProtocol = 1, + .iInterface = INDEX_MODEM, +}; + +static const struct usb_temp_interface_desc modem_iface_1 = { + .ppEndpoints = modem_iface_1_ep, + .bInterfaceClass = 10, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = INDEX_MODEM, +}; + +static const struct usb_temp_interface_desc *modem_interfaces[] = { + &modem_iface_0, + &modem_iface_1, + NULL, +}; + +static const struct usb_temp_config_desc modem_config_desc = { + .ppIfaceDesc = modem_interfaces, + .bmAttributes = UC_BUS_POWERED, + .bMaxPower = 25, /* 50 mA */ + .iConfiguration = INDEX_PRODUCT, +}; + +static const struct usb_temp_config_desc *modem_configs[] = { + &modem_config_desc, + NULL, +}; + +static usb_temp_get_string_desc_t modem_get_string_desc; +static usb_temp_get_vendor_desc_t modem_get_vendor_desc; + +const struct usb_temp_device_desc usb_template_modem = { + .getStringDesc = &modem_get_string_desc, + .getVendorDesc = &modem_get_vendor_desc, + .ppConfigDesc = modem_configs, + .idVendor = USB_TEMPLATE_VENDOR, + .idProduct = 0x000E, + .bcdDevice = 0x0100, + .bDeviceClass = UDCLASS_COMM, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .iManufacturer = 0, + .iProduct = INDEX_PRODUCT, + .iSerialNumber = 0, +}; + +/*------------------------------------------------------------------------* + * modem_get_vendor_desc + * + * Return values: + * NULL: Failure. No such vendor descriptor. + * Else: Success. Pointer to vendor descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +modem_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen) +{ + return (NULL); +} + +/*------------------------------------------------------------------------* + * modem_get_string_desc + * + * Return values: + * NULL: Failure. No such string. + * Else: Success. Pointer to string descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +modem_get_string_desc(uint16_t lang_id, uint8_t string_index) +{ + static const void *ptr[INDEX_MAX] = { + [INDEX_LANG] = &string_lang, + [INDEX_MODEM] = &string_modem, + [INDEX_PRODUCT] = &string_product, + }; + + if (string_index == 0) { + return (&string_lang); + } + if (lang_id != 0x0409) { + return (NULL); + } + if (string_index < INDEX_MAX) { + return (ptr[string_index]); + } + return (NULL); +} diff --git a/sys/dev/usb/template/usb_template_mouse.c b/sys/dev/usb/template/usb_template_mouse.c new file mode 100644 index 0000000..b0f5381 --- /dev/null +++ b/sys/dev/usb/template/usb_template_mouse.c @@ -0,0 +1,220 @@ +#include +__FBSDID("$FreeBSD$"); + +/*- + * Copyright (c) 2010 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * This file contains the USB template for an USB Mouse Device. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +enum { + INDEX_LANG, + INDEX_MOUSE, + INDEX_PRODUCT, + INDEX_MAX, +}; + +#define STRING_LANG \ + 0x09, 0x04, /* American English */ + +#define STRING_PRODUCT \ + 'M', 0, 'o', 0, 'u', 0, 's', 0, 'e', 0, ' ', 0, \ + 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \ + 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, + +#define STRING_MOUSE \ + 'M', 0, 'o', 0, 'u', 0, 's', 0, 'e', 0, ' ', 0, \ + 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0, + +/* make the real string descriptors */ + +USB_MAKE_STRING_DESC(STRING_LANG, string_lang); +USB_MAKE_STRING_DESC(STRING_MOUSE, string_mouse); +USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product); + +/* prototypes */ + +static uint8_t mouse_hid_descriptor[] = { + 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, + 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, + 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, + 0x81, 0x02, 0x95, 0x05, 0x81, 0x03, 0x05, 0x01, + 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81, + 0x25, 0x7f, 0x75, 0x08, 0x95, 0x03, 0x81, 0x06, + 0xc0, 0xc0 +}; + +static const struct usb_temp_packet_size mouse_intr_mps = { + .mps[USB_SPEED_LOW] = 8, + .mps[USB_SPEED_FULL] = 8, + .mps[USB_SPEED_HIGH] = 8, +}; + +static const struct usb_temp_interval mouse_intr_interval = { + .bInterval[USB_SPEED_LOW] = 2, + .bInterval[USB_SPEED_FULL] = 2, + .bInterval[USB_SPEED_HIGH] = 2 * 8, +}; + +static const struct usb_temp_endpoint_desc mouse_ep_0 = { + .ppRawDesc = NULL, /* no raw descriptors */ + .pPacketSize = &mouse_intr_mps, + .pIntervals = &mouse_intr_interval, + .bEndpointAddress = UE_DIR_IN, + .bmAttributes = UE_INTERRUPT, +}; + +static const struct usb_temp_endpoint_desc *mouse_endpoints[] = { + &mouse_ep_0, + NULL, +}; + +static const uint8_t mouse_raw_desc[] = { + 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(mouse_hid_descriptor), + 0x00 +}; + +static const void *mouse_iface_0_desc[] = { + mouse_raw_desc, + NULL, +}; + +static const struct usb_temp_interface_desc mouse_iface_0 = { + .ppRawDesc = mouse_iface_0_desc, + .ppEndpoints = mouse_endpoints, + .bInterfaceClass = 3, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 2, + .iInterface = INDEX_MOUSE, +}; + +static const struct usb_temp_interface_desc *mouse_interfaces[] = { + &mouse_iface_0, + NULL, +}; + +static const struct usb_temp_config_desc mouse_config_desc = { + .ppIfaceDesc = mouse_interfaces, + .bmAttributes = UC_BUS_POWERED, + .bMaxPower = 25, /* 50 mA */ + .iConfiguration = INDEX_PRODUCT, +}; + +static const struct usb_temp_config_desc *mouse_configs[] = { + &mouse_config_desc, + NULL, +}; + +static usb_temp_get_string_desc_t mouse_get_string_desc; +static usb_temp_get_vendor_desc_t mouse_get_vendor_desc; + +const struct usb_temp_device_desc usb_template_mouse = { + .getStringDesc = &mouse_get_string_desc, + .getVendorDesc = &mouse_get_vendor_desc, + .ppConfigDesc = mouse_configs, + .idVendor = USB_TEMPLATE_VENDOR, + .idProduct = 0x00AE, + .bcdDevice = 0x0100, + .bDeviceClass = UDCLASS_COMM, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .iManufacturer = 0, + .iProduct = INDEX_PRODUCT, + .iSerialNumber = 0, +}; + +/*------------------------------------------------------------------------* + * mouse_get_vendor_desc + * + * Return values: + * NULL: Failure. No such vendor descriptor. + * Else: Success. Pointer to vendor descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +mouse_get_vendor_desc(const struct usb_device_request *req, uint16_t *plen) +{ + if ((req->bmRequestType == 0x81) && (req->bRequest == 0x06) && + (req->wValue[0] == 0x00) && (req->wValue[1] == 0x22) && + (req->wIndex[1] == 0) && (req->wIndex[0] == 0)) { + + *plen = sizeof(mouse_hid_descriptor); + return (mouse_hid_descriptor); + } + return (NULL); +} + +/*------------------------------------------------------------------------* + * mouse_get_string_desc + * + * Return values: + * NULL: Failure. No such string. + * Else: Success. Pointer to string descriptor is returned. + *------------------------------------------------------------------------*/ +static const void * +mouse_get_string_desc(uint16_t lang_id, uint8_t string_index) +{ + static const void *ptr[INDEX_MAX] = { + [INDEX_LANG] = &string_lang, + [INDEX_MOUSE] = &string_mouse, + [INDEX_PRODUCT] = &string_product, + }; + + if (string_index == 0) { + return (&string_lang); + } + if (lang_id != 0x0409) { + return (NULL); + } + if (string_index < INDEX_MAX) { + return (ptr[string_index]); + } + return (NULL); +} diff --git a/sys/dev/usb/template/usb_template_msc.c b/sys/dev/usb/template/usb_template_msc.c index 598c9fd..5c05ffe 100644 --- a/sys/dev/usb/template/usb_template_msc.c +++ b/sys/dev/usb/template/usb_template_msc.c @@ -173,8 +173,8 @@ static const struct usb_temp_config_desc *msc_configs[] = { const struct usb_temp_device_desc usb_template_msc = { .getStringDesc = &msc_get_string_desc, .ppConfigDesc = msc_configs, - .idVendor = 0x0001, - .idProduct = 0x0001, + .idVendor = USB_TEMPLATE_VENDOR, + .idProduct = 0x0012, .bcdDevice = 0x0100, .bDeviceClass = UDCLASS_COMM, .bDeviceSubClass = 0, diff --git a/sys/dev/usb/template/usb_template_mtp.c b/sys/dev/usb/template/usb_template_mtp.c index ad09b58..f48fbf4 100644 --- a/sys/dev/usb/template/usb_template_mtp.c +++ b/sys/dev/usb/template/usb_template_mtp.c @@ -191,8 +191,8 @@ const struct usb_temp_device_desc usb_template_mtp = { .getStringDesc = &mtp_get_string_desc, .getVendorDesc = &mtp_get_vendor_desc, .ppConfigDesc = mtp_configs, - .idVendor = 0x0001, - .idProduct = 0x0001, + .idVendor = USB_TEMPLATE_VENDOR, + .idProduct = 0x0011, .bcdDevice = 0x0100, .bDeviceClass = 0, .bDeviceSubClass = 0, diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 452de94..d35fa10 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -39,6 +39,20 @@ #define USB_DEVICE_NAME "usbctl" #define USB_DEVICE_DIR "usb" #define USB_GENERIC_NAME "ugen" +#define USB_TEMPLATE_SYSCTL "hw.usb.template" /* integer type */ + +/* Definition of valid template sysctl values */ + +enum { + USB_TEMP_MSC, /* USB Mass Storage */ + USB_TEMP_CDCE, /* USB CDC Ethernet */ + USB_TEMP_MTP, /* Message Transfer Protocol */ + USB_TEMP_MODEM, /* USB CDC Modem */ + USB_TEMP_AUDIO, /* USB Audio */ + USB_TEMP_KBD, /* USB Keyboard */ + USB_TEMP_MOUSE, /* USB Mouse */ + USB_TEMP_MAX, +}; struct usb_read_dir { #ifdef COMPAT_32BIT diff --git a/sys/modules/usb/template/Makefile b/sys/modules/usb/template/Makefile index 362da9d..e67303e 100644 --- a/sys/modules/usb/template/Makefile +++ b/sys/modules/usb/template/Makefile @@ -31,6 +31,13 @@ S= ${.CURDIR}/../../.. KMOD= usb_template SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h usbdevs.h \ - usb_template.c usb_template_cdce.c usb_template_msc.c usb_template_mtp.c + usb_template.c \ + usb_template_audio.c \ + usb_template_cdce.c \ + usb_template_kbd.c \ + usb_template_modem.c \ + usb_template_mouse.c \ + usb_template_msc.c \ + usb_template_mtp.c .include -- cgit v1.1 From 4dfcd2be1616501e74dc674f97996af36c67580b Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 23 Jun 2011 09:42:41 +0000 Subject: Be consistent with r160968: keep autoSrcAddr flag untouched when node receives NGM_SHUTDOWN. Submitted by: pluknet --- sys/netgraph/ng_ether.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c index 5abc5aa..b51d048 100644 --- a/sys/netgraph/ng_ether.c +++ b/sys/netgraph/ng_ether.c @@ -718,7 +718,6 @@ ng_ether_shutdown(node_p node) (void)ifpromisc(priv->ifp, 0); priv->promisc = 0; } - priv->autoSrcAddr = 1; /* reset auto-src-addr flag */ NG_NODE_REVIVE(node); /* Signal ng_rmnode we are persisant */ return (0); -- cgit v1.1 From 98422c10357e3e12f390963faabf5209359c225e Mon Sep 17 00:00:00 2001 From: andreast Date: Thu, 23 Jun 2011 09:43:53 +0000 Subject: Add leading zeros when printing the stackframe on __powerpc64__. --- sys/powerpc/powerpc/db_trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/powerpc/powerpc/db_trace.c b/sys/powerpc/powerpc/db_trace.c index f783781..20de0ec 100644 --- a/sys/powerpc/powerpc/db_trace.c +++ b/sys/powerpc/powerpc/db_trace.c @@ -200,7 +200,7 @@ db_backtrace(struct thread *td, db_addr_t fp, int count) } #ifdef __powerpc64__ - db_printf("0x%16lx: ", stackframe); + db_printf("0x%016lx: ", stackframe); #else db_printf("0x%08x: ", stackframe); #endif -- cgit v1.1 From b7eb040870f8f7f13c02782685f7c8da18ca0f5c Mon Sep 17 00:00:00 2001 From: andreast Date: Thu, 23 Jun 2011 09:46:12 +0000 Subject: Fix merge typo. --- sys/powerpc/aim/mmu_oea64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index 291d89b..8f4028f 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -1715,7 +1715,7 @@ moea64_kextract(mmu_t mmu, vm_offset_t va) pvo = moea64_pvo_find_va(kernel_pmap, va); KASSERT(pvo != NULL, ("moea64_kextract: no addr found for %#" PRIxPTR, va)); - pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) + (va - PVO_VADDR(pvo)); + pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) | (va - PVO_VADDR(pvo)); PMAP_UNLOCK(kernel_pmap); return (pa); } -- cgit v1.1 From d706015f71643daedaa30613b11519d84ed98e93 Mon Sep 17 00:00:00 2001 From: hselasky Date: Thu, 23 Jun 2011 10:35:45 +0000 Subject: - Add some comments about the origin of some USB descriptors. MFC after: 7 days --- sys/dev/usb/template/usb_template_audio.c | 7 ++++++- sys/dev/usb/template/usb_template_kbd.c | 2 ++ sys/dev/usb/template/usb_template_mouse.c | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/template/usb_template_audio.c b/sys/dev/usb/template/usb_template_audio.c index 1e2e568..8e9e7f0 100644 --- a/sys/dev/usb/template/usb_template_audio.c +++ b/sys/dev/usb/template/usb_template_audio.c @@ -95,7 +95,12 @@ USB_MAKE_STRING_DESC(STRING_AUDIO_PRODUCT, string_audio_product); /* prototypes */ -/* Audio Mixer description structures */ +/* + * Audio Mixer description structures + * + * Some of the audio descriptors were dumped + * from a Creative Labs USB audio device. + */ static const uint8_t audio_raw_desc_0[] = { 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02, diff --git a/sys/dev/usb/template/usb_template_kbd.c b/sys/dev/usb/template/usb_template_kbd.c index 4a9b9da..8928c06 100644 --- a/sys/dev/usb/template/usb_template_kbd.c +++ b/sys/dev/usb/template/usb_template_kbd.c @@ -94,6 +94,8 @@ static const struct usb_temp_interval keyboard_intr_interval = { .bInterval[USB_SPEED_HIGH] = 2 * 8, }; +/* The following HID descriptor was dumped from a HP keyboard. */ + static uint8_t keyboard_hid_descriptor[] = { 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, diff --git a/sys/dev/usb/template/usb_template_mouse.c b/sys/dev/usb/template/usb_template_mouse.c index b0f5381..3ff0fb0 100644 --- a/sys/dev/usb/template/usb_template_mouse.c +++ b/sys/dev/usb/template/usb_template_mouse.c @@ -82,6 +82,8 @@ USB_MAKE_STRING_DESC(STRING_PRODUCT, string_product); /* prototypes */ +/* The following HID descriptor was dumped from a HP mouse. */ + static uint8_t mouse_hid_descriptor[] = { 0x05, 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, -- cgit v1.1 From 448b26fea81ffda0c5ca4877fa8134c0682b4699 Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 23 Jun 2011 10:43:36 +0000 Subject: Document that autoSrcAddr isn't re-enabled on NGM_SHUTDOWN. Submitted by: Vadim Goncharov --- share/man/man4/ng_ether.4 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/share/man/man4/ng_ether.4 b/share/man/man4/ng_ether.4 index 9fd409d..6ca5c11 100644 --- a/share/man/man4/ng_ether.4 +++ b/share/man/man4/ng_ether.4 @@ -34,7 +34,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 4, 2006 +.Dd June 23, 2011 .Dt NG_ETHER 4 .Os .Sh NAME @@ -183,7 +183,6 @@ Detach from underlying Ethernet interface and shut down node. Upon receipt of the .Dv NGM_SHUTDOWN control message, all hooks are disconnected, promiscuous mode is disabled, -and the source address override flag is re-enabled, but the node is not removed. Node can be shut down only using .Dv NGM_ETHER_DETACH -- cgit v1.1 From de5d2ef6140fa8edbd997bcacb0f51ec0a995e71 Mon Sep 17 00:00:00 2001 From: adrian Date: Thu, 23 Jun 2011 12:11:43 +0000 Subject: add missing #define for the non-debug case. --- sys/dev/ath/ath_hal/ah_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h index 0959218..2bb163f 100644 --- a/sys/dev/ath/ath_hal/ah_internal.h +++ b/sys/dev/ath/ath_hal/ah_internal.h @@ -529,6 +529,7 @@ extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) __printflike(3,4); #else #define HALDEBUG(_ah, __m, _fmt, ...) +#define HALDEBUG_G(_ah, __m, _fmt, ...) #endif /* AH_DEBUG */ /* -- cgit v1.1 From c2a28c3cb627963211946418ed99ca5d3b152f7d Mon Sep 17 00:00:00 2001 From: mav Date: Thu, 23 Jun 2011 15:10:44 +0000 Subject: Fix ATAPI breakage introduced by r223443. It made SCSI commands to ATAPI device to never complete, that caused probe process (system boot) stuck. --- sys/cam/ata/ata_xpt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index 216805d..84ab46b 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -1678,7 +1678,8 @@ ata_action(union ccb *start_ccb) xpt_done(start_ccb); break; } - /* FALLTHROUGH */ + xpt_action_default(start_ccb); + break; } case XPT_DEV_ADVINFO: { -- cgit v1.1 From 6e30ce7ac2c9a84e443253ce8de8bbd54b0f0361 Mon Sep 17 00:00:00 2001 From: jhb Date: Thu, 23 Jun 2011 15:53:17 +0000 Subject: The recent change to increase the zfsboot size to 64k made a few BIOSes unhappy (probably they don't handle crossing the 64k boundary, etc.). Fix this by changing zfsldr to use a loop reading from the disk one sector at a time. To avoid trashing the saved copy of the MBR which is used for disk I/O, read zfsboot2 at address 0x9000. This has the advantage that BTX no longer needs to be relocated as it is read into the correct location. However, the loop to relocate zfsboot2.bin can now cross a 64k boundary, so change it to use relative segments instead. (This will need further work if zfsboot2.bin ever exceeds 64k.) While here, stop storing a relocated copy of zfsldr at 0x700. This was only used by the xread hack which has recently been removed (and even that use was dubious). Also, include the BIOS error code as hex when reporting read errors to aid in debugging. Much thanks to Henri Hennebert for patiently testing various iterations of the patch as well as fixing the zfsboot2.bin relocation to use relative segments. MFC after: 1 week --- sys/boot/i386/zfsboot/zfsldr.S | 125 +++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/sys/boot/i386/zfsboot/zfsldr.S b/sys/boot/i386/zfsboot/zfsldr.S index 182d88e..471a042 100644 --- a/sys/boot/i386/zfsboot/zfsldr.S +++ b/sys/boot/i386/zfsboot/zfsldr.S @@ -16,7 +16,6 @@ */ /* Memory Locations */ - .set MEM_REL,0x700 # Relocation address .set MEM_ARG,0x900 # Arguments .set MEM_ORG,0x7c00 # Origin .set MEM_BUF,0x8000 # Load area @@ -91,26 +90,18 @@ main: cld # String ops inc mov %cx,%ss # Set up mov $start,%sp # stack /* - * Relocate ourself to MEM_REL. Since %cx == 0, the inc %ch sets - * %cx == 0x100. - */ - mov %sp,%si # Source - mov $MEM_REL,%di # Destination - incb %ch # Word count - rep # Copy - movsw # code -/* * If we are on a hard drive, then load the MBR and look for the first * FreeBSD slice. We use the fake partition entry below that points to * the MBR when we call nread. The first pass looks for the first active * FreeBSD slice. The second pass looks for the first non-active FreeBSD * slice if the first one fails. */ - mov $part4,%si # Partition + mov $part4,%si # Dummy partition cmpb $0x80,%dl # Hard drive? jb main.4 # No - movb $0x1,%dh # Block count - callw nread # Read MBR + xor %eax,%eax # Read MBR + movl $MEM_BUF,%ebx # from first + callw nread # sector mov $0x1,%cx # Two passes main.1: mov $MEM_BUF+PRT_OFF,%si # Partition table movb $0x1,%dh # Partition @@ -139,52 +130,51 @@ main.4: xor %dx,%dx # Partition:drive /* * Ok, we have a slice and drive in %dx now, so use that to locate and * load boot2. %si references the start of the slice we are looking - * for, so go ahead and load up the 64 sectors starting at sector 1024 + * for, so go ahead and load up the 128 sectors starting at sector 1024 * (i.e. after the two vdev labels). We don't have do anything fancy * here to allow for an extra copy of boot1 and a partition table * (compare to this section of the UFS bootstrap) so we just load it - * all at 0x8000. The first part of boot2 is BTX, which wants to run + * all at 0x9000. The first part of boot2 is BTX, which wants to run * at 0x9000. The boot2.bin binary starts right after the end of BTX, * so we have to figure out where the start of it is and then move the - * binary to 0xc000. After we have moved the client, we relocate BTX - * itself to 0x9000 - doing it in this order means that none of the - * memcpy regions overlap which would corrupt the copy. Normally, BTX - * clients start at MEM_USR, or 0xa000, but when we use btxld to - * create zfsboot2, we use an entry point of 0x2000. That entry point is - * relative to MEM_USR; thus boot2.bin starts at 0xc000. + * binary to 0xc000. Normally, BTX clients start at MEM_USR, or 0xa000, + * but when we use btxld to create zfsboot2, we use an entry point of + * 0x2000. That entry point is relative to MEM_USR; thus boot2.bin + * starts at 0xc000. * * The load area and the target area for the client overlap so we have * to use a decrementing string move. We also play segment register * games with the destination address for the move so that the client * can be larger than 16k (which would overflow the zero segment since - * the client starts at 0xc000). Relocating BTX is easy since the load - * area and target area do not overlap. + * the client starts at 0xc000). */ main.5: mov %dx,MEM_ARG # Save args - movb $NSECT,%dh # Sector count + mov $NSECT,%cx # Sector count movl $1024,%eax # Offset to boot2 - callw nread.1 # Read disk -main.6: mov $MEM_BUF,%si # BTX (before reloc) - mov 0xa(%si),%bx # Get BTX length and set + mov $MEM_BTX,%ebx # Destination buffer +main.6: pushal # Save params + callw nread # Read disk + popal # Restore + incl %eax # Advance to + add $SIZ_SEC,%ebx # next sector + loop main.6 # If not last, read another + mov MEM_BTX+0xa,%bx # Get BTX length mov $NSECT*SIZ_SEC-1,%di # Size of load area (less one) - mov %di,%si # End of load - add $MEM_BUF,%si # area + mov %di,%si # End of load area, 0x9000 rel sub %bx,%di # End of client, 0xc000 rel mov %di,%cx # Size of inc %cx # client + mov $(MEM_BTX)>>4,%dx # Segment + mov %dx,%ds # addressing 0x9000 mov $(MEM_USR+2*SIZ_PAG)>>4,%dx # Segment mov %dx,%es # addressing 0xc000 std # Move with decrement rep # Relocate movsb # client - mov %ds,%dx # Back to - mov %dx,%es # zero segment - mov $MEM_BUF,%si # BTX (before reloc) - mov $MEM_BTX,%di # BTX - mov %bx,%cx # Get BTX length - cld # Increment this time - rep # Relocate - movsb # BTX + cld # Back to increment + xor %dx,%dx # Back + mov %ds,%dx # to zero + mov %dx,%es # segment /* * Enable A20 so we can access memory above 1 meg. @@ -211,32 +201,35 @@ seta20.3: sti # Enable interrupts /* * Trampoline used to call read from within zfsldr. Sets up an EDD - * packet on the stack and passes it to read. + * packet on the stack and passes it to read. We assume that the + * destination address is always segment-aligned. * * %eax - int - LBA to read in relative to partition start + * %ebx - ptr - destination address * %dl - byte - drive to read from - * %dh - byte - num sectors to read * %si - ptr - MBR partition entry */ -nread: xor %eax,%eax # Sector offset in partition -nread.1: xor %ecx,%ecx # Get +nread: xor %ecx,%ecx # Get addl 0x8(%si),%eax # LBA adc $0,%ecx pushl %ecx # Starting absolute block pushl %eax # block number - push %es # Address of - push $MEM_BUF # transfer buffer - xor %ax,%ax # Number of - movb %dh,%al # blocks to - push %ax # transfer + shr $4,%ebx # Convert to segment + push %bx # Address of + push $0 # transfer buffer + push $0x1 # Read 1 sector push $0x10 # Size of packet mov %sp,%bp # Packet pointer callw read # Read from disk + jc nread.1 # If error, fail lea 0x10(%bp),%sp # Clear stack - jnc return # If success, return - mov $msg_read,%si # Otherwise, set the error - # message and fall through to - # the error routine + ret # If success, return +nread.1: mov %ah,%al # Format + mov $read_err,%di # error + call hex8 # code + mov $msg_read,%si # Set the error message and + # fall through to the error + # routine /* * Print out the error message pointed to by %ds:(%si) followed * by a prompt, wait for a keypress, and then reboot the machine. @@ -259,14 +252,6 @@ putstr: lodsb # Get char jne putstr.0 # No /* - * Overused return code. ereturn is used to return an error from the - * read function. Since we assume putstr succeeds, we (ab)use the - * same code when we return from putstr. - */ -ereturn: movb $0x1,%ah # Invalid - stc # argument -return: retw # To caller -/* * Reads sectors from the disk. If EDD is enabled, then check if it is * installed and use it if it is. If it is not installed or not enabled, then * fall back to using CHS. Since we use a LBA, if we are using CHS, we have to @@ -294,14 +279,30 @@ read: cmpb $0x80,%dl # Hard drive? retw # To caller read.1: mov $msg_chs,%si jmp error -msg_chs: .asciz "CHS not supported" + +/* + * AL to hex, saving the result to [EDI]. + */ +hex8: push %ax # Save + shrb $0x4,%al # Do upper + call hex8.1 # 4 + pop %ax # Restore +hex8.1: andb $0xf,%al # Get lower 4 + cmpb $0xa,%al # Convert + sbbb $0x69,%al # to hex + das # digit + orb $0x20,%al # To lower case + stosb # Save char + ret # (Recursive) /* Messages */ -msg_read: .asciz "Read" -msg_part: .asciz "Boot" +msg_chs: .asciz "CHS not supported" +msg_read: .ascii "Read error: " +read_err: .asciz "XX" +msg_part: .asciz "Boot error" -prompt: .asciz " error\r\n" +prompt: .asciz "\r\n" .org PRT_OFF,0x90 -- cgit v1.1 From 594e41652df1d0b6c71e43141f9f25d0dfca2a21 Mon Sep 17 00:00:00 2001 From: marcel Date: Thu, 23 Jun 2011 16:21:43 +0000 Subject: Unblock the outgoing thread after we performed pmap_switch() to switch the region registers. pmap_switch() returns the pmap for which the region register are currently programmed, which needs to be re-programmed on the CPU the ougoing thread gets switched in. This change does not noticibly change anything or fix known bugs, but does give me a warm fuzzy feeling by being more correct. --- sys/ia64/ia64/machdep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index f3105fc..185e13c 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -470,12 +470,12 @@ cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx) if (PCPU_GET(fpcurthread) == old) old->td_frame->tf_special.psr |= IA64_PSR_DFH; if (!savectx(oldpcb)) { - atomic_store_rel_ptr(&old->td_lock, mtx); - newpcb = new->td_pcb; oldpcb->pcb_current_pmap = pmap_switch(newpcb->pcb_current_pmap); + atomic_store_rel_ptr(&old->td_lock, mtx); + #if defined(SCHED_ULE) && defined(SMP) while (atomic_load_acq_ptr(&new->td_lock) == &blocked_lock) cpu_spinwait(); -- cgit v1.1 From 258f54d7675dfc59ad893a6433815f854e0467a1 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 23 Jun 2011 16:34:41 +0000 Subject: Clear any outstanding atomic reservations when traps are taken. This fixes some interesting bugs (mostly on SMP systems) with atomic operations silently failing in interrupt heavy situations, especially when using overflow pages. --- sys/powerpc/aim/trap_subr32.S | 2 ++ sys/powerpc/aim/trap_subr64.S | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sys/powerpc/aim/trap_subr32.S b/sys/powerpc/aim/trap_subr32.S index 7c154a8..80329cd 100644 --- a/sys/powerpc/aim/trap_subr32.S +++ b/sys/powerpc/aim/trap_subr32.S @@ -748,6 +748,8 @@ k_trap: /* Call C interrupt dispatcher: */ trapagain: addi %r3,%r1,8 + addi %r4,%r1,-4 /* Clear any existing reservations */ + stwcx. %r3,0,%r4 bl CNAME(powerpc_interrupt) .globl CNAME(trapexit) /* backtrace code sentinel */ CNAME(trapexit): diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S index 5d4148a..66c543f 100644 --- a/sys/powerpc/aim/trap_subr64.S +++ b/sys/powerpc/aim/trap_subr64.S @@ -508,6 +508,8 @@ trapagain: lis %r3,tocbase@ha ld %r2,tocbase@l(%r3) addi %r3,%r1,48 + addi %r4,%r1,-8 /* Clear any existing reservations */ + stdcx. %r3,0,%r4 bl CNAME(powerpc_interrupt) nop -- cgit v1.1 From 4a9f970de4a7f79286fa73de073a7c44187a9f60 Mon Sep 17 00:00:00 2001 From: jfv Date: Thu, 23 Jun 2011 17:42:27 +0000 Subject: Put back the global for rx processing due to popular demand. --- sys/dev/e1000/if_igb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c index 08735ac..a1a14b6 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -346,6 +346,10 @@ TUNABLE_INT("hw.igb.hdr_split", &igb_header_split); static int igb_num_queues = 0; TUNABLE_INT("hw.igb.num_queues", &igb_num_queues); +/* How many packets rxeof tries to clean at a time */ +static int igb_rx_process_limit = 100; +TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit); + /********************************************************************* * Device identification routine * @@ -465,7 +469,7 @@ igb_attach(device_t dev) /* Sysctl for limiting the amount of work done in the taskqueue */ igb_set_sysctl_value(adapter, "rx_processing_limit", "max number of rx packets to process", - &adapter->rx_process_limit, 100); + &adapter->rx_process_limit, igb_rx_process_limit); /* * Validate number of transmit and receive descriptors. It -- cgit v1.1 From 484c74853314285d6c33b76eff2f8fa4825cf4e3 Mon Sep 17 00:00:00 2001 From: uqs Date: Thu, 23 Jun 2011 20:31:52 +0000 Subject: Fix make buildworld -DMODULES_WITH_WORLD Sort opt_ srcs --- sys/modules/cxgbe/if_cxgbe/Makefile | 1 + sys/modules/nfscl/Makefile | 9 +++++---- sys/modules/nfscommon/Makefile | 7 ++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/sys/modules/cxgbe/if_cxgbe/Makefile b/sys/modules/cxgbe/if_cxgbe/Makefile index ac1d22c..e4e69e6 100644 --- a/sys/modules/cxgbe/if_cxgbe/Makefile +++ b/sys/modules/cxgbe/if_cxgbe/Makefile @@ -10,6 +10,7 @@ SRCS = t4_main.c t4_sge.c t4_l2t.c SRCS+= t4_hw.c SRCS+= device_if.h bus_if.h pci_if.h SRCS+= opt_inet.h +SRCS+= opt_ofed.h CFLAGS+= -I${CXGBE} diff --git a/sys/modules/nfscl/Makefile b/sys/modules/nfscl/Makefile index 46fa327..a9b2003 100644 --- a/sys/modules/nfscl/Makefile +++ b/sys/modules/nfscl/Makefile @@ -14,13 +14,14 @@ SRCS= vnode_if.h \ nfs_clsubs.c \ nfs_clvfsops.c \ nfs_clvnops.c \ + opt_bootp.h \ opt_inet.h \ opt_inet6.h \ - opt_bootp.h \ - opt_nfsroot.h \ + opt_kdtrace.h \ + opt_kgssapi.h \ opt_nfs.h \ - opt_ufs.h \ - opt_kgssapi.h + opt_nfsroot.h \ + opt_ufs.h .if !defined(KERNBUILDDIR) NFS_INET?= 1 # 0/1 - requires INET to be configured in kernel diff --git a/sys/modules/nfscommon/Makefile b/sys/modules/nfscommon/Makefile index a3d75a7..2a6b8f7 100644 --- a/sys/modules/nfscommon/Makefile +++ b/sys/modules/nfscommon/Makefile @@ -7,9 +7,10 @@ SRCS= vnode_if.h \ nfs_commonkrpc.c \ nfs_commonport.c \ nfs_commonsubs.c \ - opt_kgssapi.h \ - opt_ufs.h \ opt_inet6.h \ - opt_nfs.h + opt_kdtrace.h \ + opt_kgssapi.h \ + opt_nfs.h \ + opt_ufs.h .include -- cgit v1.1 From 1f9c357d9bfe97631d50ce6a97e271360f417bbb Mon Sep 17 00:00:00 2001 From: dim Date: Thu, 23 Jun 2011 20:54:44 +0000 Subject: Make GNU as recognize the ARM 'rrx' mnemonic, which can be generated by clang for certain expressions. Code taken from Apple cctools (GPLv2). Submitted by: damjan.marion@gmail.com --- contrib/binutils/gas/config/tc-arm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/contrib/binutils/gas/config/tc-arm.c b/contrib/binutils/gas/config/tc-arm.c index 683e6ee..c48a758 100644 --- a/contrib/binutils/gas/config/tc-arm.c +++ b/contrib/binutils/gas/config/tc-arm.c @@ -9974,6 +9974,13 @@ do_t_rbit (void) } static void +do_t_rd_rm (void) +{ + inst.instruction |= inst.operands[0].reg << 8; + inst.instruction |= inst.operands[1].reg; +} + +static void do_t_rev (void) { if (inst.operands[0].reg <= 7 && inst.operands[1].reg <= 7 @@ -14901,6 +14908,9 @@ static const struct asm_opcode insns[] = TCE(rsb, 0600000, ebc00000, 3, (RR, oRR, SH), arit, t_rsb), TC3(rsbs, 0700000, ebd00000, 3, (RR, oRR, SH), arit, t_rsb), + TCE(rrx, 1a00060, ea4f0030, 2, (RR, RR), rd_rm, t_rd_rm), + TCE(rrxs, 1b00060, ea5f0030, 2, (RR, RR), rd_rm, t_rd_rm), + #undef THUMB_VARIANT #define THUMB_VARIANT &arm_ext_v6 TCE(cpy, 1a00000, 4600, 2, (RR, RR), rd_rm, t_cpy), -- cgit v1.1 From 1d215b1285ab0897c64a473f1b6b30f0311b87d0 Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Thu, 23 Jun 2011 22:21:28 +0000 Subject: Use the ABI-mandated thread pointer register (r2 for ppc32, r13 for ppc64) instead of a PCPU field for curthread. This averts a race on SMP systems with a high interrupt rate where the thread looking up the value of curthread could be preempted and migrated between obtaining the PCPU pointer and reading the value of pc_curthread, resulting in curthread being observed to be the current thread on the thread's original CPU. This played merry havoc with the system, in particular with mutexes. Many thanks to jhb for helping me work this one out. Note that Book-E is in principle susceptible to the same problem, but has not been modified yet due to lack of Book-E hardware. MFC after: 2 weeks --- sys/powerpc/aim/copyinout.c | 22 +++++++++++----------- sys/powerpc/aim/locore32.S | 3 +-- sys/powerpc/aim/locore64.S | 3 +-- sys/powerpc/aim/machdep.c | 4 ++-- sys/powerpc/aim/mp_cpudep.c | 2 +- sys/powerpc/aim/swtch32.S | 18 ++++++++---------- sys/powerpc/aim/swtch64.S | 18 ++++++++---------- sys/powerpc/aim/trap.c | 6 +++--- sys/powerpc/aim/trap_subr32.S | 14 ++++++++++---- sys/powerpc/aim/trap_subr64.S | 13 +++++++++---- sys/powerpc/booke/copyinout.c | 16 ++++++++-------- sys/powerpc/booke/interrupt.c | 2 +- sys/powerpc/booke/trap.c | 6 +++--- sys/powerpc/include/pcpu.h | 8 ++++++++ sys/powerpc/ofw/ofwcall32.S | 14 ++++++++------ sys/powerpc/powerpc/mp_machdep.c | 4 ---- 16 files changed, 82 insertions(+), 71 deletions(-) diff --git a/sys/powerpc/aim/copyinout.c b/sys/powerpc/aim/copyinout.c index 3592691..69ba431 100644 --- a/sys/powerpc/aim/copyinout.c +++ b/sys/powerpc/aim/copyinout.c @@ -142,7 +142,7 @@ copyout(const void *kaddr, void *udaddr, size_t len) char *up, *p; size_t l; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; if (setfault(env)) { @@ -183,7 +183,7 @@ copyin(const void *udaddr, void *kaddr, size_t len) char *kp, *p; size_t l; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; if (setfault(env)) { @@ -225,7 +225,7 @@ copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) size_t l; int rv, c; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; if (setfault(env)) { @@ -267,7 +267,7 @@ subyte(void *addr, int byte) faultbuf env; char *p; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (char *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); @@ -293,7 +293,7 @@ suword32(void *addr, int word) faultbuf env; int *p; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (int *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); @@ -319,7 +319,7 @@ suword(void *addr, long word) faultbuf env; long *p; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (long *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); @@ -359,7 +359,7 @@ fubyte(const void *addr) u_char *p; int val; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (u_char *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); @@ -385,7 +385,7 @@ fuword32(const void *addr) faultbuf env; int32_t *p, val; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (int32_t *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); @@ -411,7 +411,7 @@ fuword(const void *addr) faultbuf env; long *p, val; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (long *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); @@ -444,7 +444,7 @@ casuword32(volatile uint32_t *addr, uint32_t old, uint32_t new) faultbuf env; uint32_t *p, val; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (uint32_t *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); @@ -489,7 +489,7 @@ casuword(volatile u_long *addr, u_long old, u_long new) faultbuf env; u_long *p, val; - td = PCPU_GET(curthread); + td = curthread; pm = &td->td_proc->p_vmspace->vm_pmap; p = (u_long *)(USER_ADDR + ((uintptr_t)addr & ~SEGMENT_MASK)); diff --git a/sys/powerpc/aim/locore32.S b/sys/powerpc/aim/locore32.S index 35ea99b..d0a3778 100644 --- a/sys/powerpc/aim/locore32.S +++ b/sys/powerpc/aim/locore32.S @@ -181,8 +181,7 @@ setfault: mflr 0 mfcr 12 mfsprg 4,0 - lwz 4,PC_CURTHREAD(4) - lwz 4,TD_PCB(4) + lwz 4,TD_PCB(2) /* curthread = r2 */ stw 3,PCB_ONFAULT(4) stw 0,0(3) stw 1,4(3) diff --git a/sys/powerpc/aim/locore64.S b/sys/powerpc/aim/locore64.S index c200b4c..5af5e3a 100644 --- a/sys/powerpc/aim/locore64.S +++ b/sys/powerpc/aim/locore64.S @@ -203,8 +203,7 @@ ASENTRY(setfault) mflr 0 mfcr 12 mfsprg 4,0 - ld 4,PC_CURTHREAD(4) - ld 4,TD_PCB(4) + ld 4,TD_PCB(13) /* curthread = r13 */ std 3,PCB_ONFAULT(4) std 0,0(3) std 1,8(3) diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index 3ccae91..c368c68 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -303,7 +303,7 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel, */ pc = __pcpu; pcpu_init(pc, 0, sizeof(struct pcpu)); - pc->pc_curthread = &thread0; + curthread_reg = pc->pc_curthread = &thread0; pc->pc_cpuid = 0; __asm __volatile("mtsprg 0, %0" :: "r"(pc)); @@ -745,7 +745,7 @@ kcopy(const void *src, void *dst, size_t len) faultbuf env, *oldfault; int rv; - td = PCPU_GET(curthread); + td = curthread; oldfault = td->td_pcb->pcb_onfault; if ((rv = setfault(env)) != 0) { td->td_pcb->pcb_onfault = oldfault; diff --git a/sys/powerpc/aim/mp_cpudep.c b/sys/powerpc/aim/mp_cpudep.c index d617fde..68fe517 100644 --- a/sys/powerpc/aim/mp_cpudep.c +++ b/sys/powerpc/aim/mp_cpudep.c @@ -88,7 +88,7 @@ cpudep_ap_bootstrap(void) msr = PSL_KERNSET & ~PSL_EE; mtmsr(msr); - pcpup->pc_curthread = pcpup->pc_idlethread; + curthread_reg = pcpup->pc_curthread = pcpup->pc_idlethread; pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb; sp = pcpup->pc_curpcb->pcb_sp; diff --git a/sys/powerpc/aim/swtch32.S b/sys/powerpc/aim/swtch32.S index cd141aa..a44b861 100644 --- a/sys/powerpc/aim/swtch32.S +++ b/sys/powerpc/aim/swtch32.S @@ -69,7 +69,7 @@ * void cpu_throw(struct thread *old, struct thread *new) */ ENTRY(cpu_throw) - mr %r15, %r4 + mr %r2, %r4 b cpu_switchin /* @@ -89,10 +89,9 @@ ENTRY(cpu_switch) mflr %r16 /* Save the link register */ stw %r16,PCB_LR(%r6) stw %r1,PCB_SP(%r6) /* Save the stack pointer */ - stw %r2,PCB_TOC(%r6) /* Save the TOC pointer */ mr %r14,%r3 /* Copy the old thread ptr... */ - mr %r15,%r4 /* and the new thread ptr in scratch */ + mr %r2,%r4 /* and the new thread ptr in curthread */ mr %r16,%r5 /* and the new lock */ mr %r17,%r6 /* and the PCB */ @@ -122,24 +121,24 @@ cpu_switchin: lis %r6,blocked_lock@ha addi %r6,%r6,blocked_lock@l blocked_loop: - lwz %r7,TD_LOCK(%r15) + lwz %r7,TD_LOCK(%r2) cmpw %r6,%r7 beq blocked_loop #endif mfsprg %r7,0 /* Get the pcpu pointer */ - stw %r15,PC_CURTHREAD(%r7) /* Store new current thread */ - lwz %r17,TD_PCB(%r15) /* Store new current PCB */ + stw %r2,PC_CURTHREAD(%r7) /* Store new current thread */ + lwz %r17,TD_PCB(%r2) /* Store new current PCB */ stw %r17,PC_CURPCB(%r7) - mr %r3,%r15 /* Get new thread ptr */ + mr %r3,%r2 /* Get new thread ptr */ bl pmap_activate /* Activate the new address space */ lwz %r6, PCB_FLAGS(%r17) /* Restore FPU context if needed */ andi. %r6, %r6, PCB_FPU beq .L3 - mr %r3,%r15 /* Pass curthread to enable_fpu */ + mr %r3,%r2 /* Pass curthread to enable_fpu */ bl enable_fpu .L3: @@ -147,7 +146,7 @@ blocked_loop: /* Restore Altivec context if needed */ andi. %r6, %r6, PCB_VEC beq .L4 - mr %r3,%r15 /* Pass curthread to enable_vec */ + mr %r3,%r2 /* Pass curthread to enable_vec */ bl enable_vec /* thread to restore is in r3 */ @@ -163,7 +162,6 @@ blocked_loop: mtsr USER_SR,%r5 isync lwz %r1,PCB_SP(%r3) /* Load the stack pointer */ - lwz %r2,PCB_TOC(%r3) /* Load the TOC pointer */ /* * Perform a dummy stwcx. to clear any reservations we may have * inherited from the previous thread. It doesn't matter if the diff --git a/sys/powerpc/aim/swtch64.S b/sys/powerpc/aim/swtch64.S index 1877e8d..c5cdcbc 100644 --- a/sys/powerpc/aim/swtch64.S +++ b/sys/powerpc/aim/swtch64.S @@ -69,7 +69,7 @@ * void cpu_throw(struct thread *old, struct thread *new) */ ENTRY(cpu_throw) - mr %r15, %r4 + mr %r13, %r4 b cpu_switchin /* @@ -83,7 +83,6 @@ ENTRY(cpu_switch) ld %r6,TD_PCB(%r3) /* Get the old thread's PCB ptr */ std %r12,PCB_CONTEXT(%r6) /* Save the non-volatile GP regs. These can now be used for scratch */ - std %r13,PCB_CONTEXT+1*8(%r6) std %r14,PCB_CONTEXT+2*8(%r6) std %r15,PCB_CONTEXT+3*8(%r6) std %r16,PCB_CONTEXT+4*8(%r6) @@ -111,7 +110,7 @@ ENTRY(cpu_switch) std %r2,PCB_TOC(%r6) /* Save the TOC pointer */ mr %r14,%r3 /* Copy the old thread ptr... */ - mr %r15,%r4 /* and the new thread ptr in scratch */ + mr %r13,%r4 /* and the new thread ptr in curthread*/ mr %r16,%r5 /* and the new lock */ mr %r17,%r6 /* and the PCB */ @@ -148,19 +147,19 @@ cpu_switchin: lis %r6,blocked_lock@ha addi %r6,%r6,blocked_lock@l blocked_loop: - ld %r7,TD_LOCK(%r15) + ld %r7,TD_LOCK(%r13) cmpd %r6,%r7 beq blocked_loop #endif mfsprg %r7,0 /* Get the pcpu pointer */ - std %r15,PC_CURTHREAD(%r7) /* Store new current thread */ - ld %r17,TD_PCB(%r15) /* Store new current PCB */ + std %r13,PC_CURTHREAD(%r7) /* Store new current thread */ + ld %r17,TD_PCB(%r13) /* Store new current PCB */ std %r17,PC_CURPCB(%r7) stdu %r1,-48(%r1) - mr %r3,%r15 /* Get new thread ptr */ + mr %r3,%r13 /* Get new thread ptr */ bl pmap_activate /* Activate the new address space */ nop @@ -168,7 +167,7 @@ blocked_loop: /* Restore FPU context if needed */ andi. %r6, %r6, PCB_FPU beq .L3 - mr %r3,%r15 /* Pass curthread to enable_fpu */ + mr %r3,%r13 /* Pass curthread to enable_fpu */ bl enable_fpu nop @@ -177,7 +176,7 @@ blocked_loop: /* Restore Altivec context if needed */ andi. %r6, %r6, PCB_VEC beq .L4 - mr %r3,%r15 /* Pass curthread to enable_vec */ + mr %r3,%r13 /* Pass curthread to enable_vec */ bl enable_vec nop @@ -186,7 +185,6 @@ blocked_loop: addi %r1,%r1,48 mr %r3,%r17 /* Recover PCB ptr */ ld %r12,PCB_CONTEXT(%r3) /* Load the non-volatile GP regs. */ - ld %r13,PCB_CONTEXT+1*8(%r3) ld %r14,PCB_CONTEXT+2*8(%r3) ld %r15,PCB_CONTEXT+3*8(%r3) ld %r16,PCB_CONTEXT+4*8(%r3) diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index 60c0f3b..51dee0e 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -149,7 +149,7 @@ trap(struct trapframe *frame) PCPU_INC(cnt.v_trap); - td = PCPU_GET(curthread); + td = curthread; p = td->td_proc; type = ucode = frame->exc; @@ -452,7 +452,7 @@ syscall(struct trapframe *frame) struct syscall_args sa; int error; - td = PCPU_GET(curthread); + td = curthread; td->td_frame = frame; #ifdef __powerpc64__ @@ -600,7 +600,7 @@ badaddr_read(void *addr, size_t size, int *rptr) /* Get rid of any stale machine checks that have been waiting. */ __asm __volatile ("sync; isync"); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = 0; diff --git a/sys/powerpc/aim/trap_subr32.S b/sys/powerpc/aim/trap_subr32.S index 80329cd..f00020b 100644 --- a/sys/powerpc/aim/trap_subr32.S +++ b/sys/powerpc/aim/trap_subr32.S @@ -155,9 +155,15 @@ stw %r28,FRAME_AIM_DAR+8(1); \ stw %r29,FRAME_AIM_DSISR+8(1); /* save dsisr/srr0/srr1 */ \ stw %r30,FRAME_SRR0+8(1); \ - stw %r31,FRAME_SRR1+8(1) + stw %r31,FRAME_SRR1+8(1); \ + lwz %r2,PC_CURTHREAD(%r2) /* set curthread pointer */ #define FRAME_LEAVE(savearea) \ +/* Disable exceptions: */ \ + mfmsr %r2; \ + andi. %r2,%r2,~PSL_EE@l; \ + mtmsr %r2; \ + isync; \ /* Now restore regs: */ \ lwz %r2,FRAME_SRR0+8(%r1); \ lwz %r3,FRAME_SRR1+8(%r1); \ @@ -209,7 +215,7 @@ mtsprg3 %r3; \ /* Disable translation, machine check and recoverability: */ \ mfmsr %r2; \ - andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l; \ + andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ mtmsr %r2; \ isync; \ /* Decide whether we return to user mode: */ \ @@ -764,8 +770,8 @@ CNAME(trapexit): bf 17,1f /* branch if PSL_PR is false */ GET_CPUINFO(%r3) /* get per-CPU pointer */ - lwz %r4, PC_CURTHREAD(%r3) /* deref to get curthread */ - lwz %r4, TD_FLAGS(%r4) /* get thread flags value */ + lwz %r4, TD_FLAGS(%r2) /* get thread flags value + * (r2 is curthread) */ lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h ori %r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l and. %r4,%r4,%r5 diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S index 66c543f..1ec8507 100644 --- a/sys/powerpc/aim/trap_subr64.S +++ b/sys/powerpc/aim/trap_subr64.S @@ -179,9 +179,15 @@ restore_kernsrs: std %r28,FRAME_AIM_DAR+48(1); \ std %r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */ \ std %r30,FRAME_SRR0+48(1); \ - std %r31,FRAME_SRR1+48(1) + std %r31,FRAME_SRR1+48(1); \ + ld %r13,PC_CURTHREAD(%r2) /* set kernel curthread */ #define FRAME_LEAVE(savearea) \ +/* Disable exceptions: */ \ + mfmsr %r2; \ + andi. %r2,%r2,~PSL_EE@l; \ + mtmsr %r2; \ + isync; \ /* Now restore regs: */ \ ld %r2,FRAME_SRR0+48(%r1); \ ld %r3,FRAME_SRR1+48(%r1); \ @@ -233,7 +239,7 @@ restore_kernsrs: mtsprg3 %r3; \ /* Disable translation, machine check and recoverability: */ \ mfmsr %r2; \ - andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l; \ + andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_ME|PSL_RI)@l; \ mtmsr %r2; \ isync; \ /* Decide whether we return to user mode: */ \ @@ -526,8 +532,7 @@ CNAME(trapexit): bf 17,1f /* branch if PSL_PR is false */ GET_CPUINFO(%r3) /* get per-CPU pointer */ - ld %r4, PC_CURTHREAD(%r3) /* deref to get curthread */ - lwz %r4, TD_FLAGS(%r4) /* get thread flags value */ + lwz %r4, TD_FLAGS(%r13) /* get thread flags value */ lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h ori %r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l and. %r4,%r4,%r5 diff --git a/sys/powerpc/booke/copyinout.c b/sys/powerpc/booke/copyinout.c index 91195dd..011b8bd 100644 --- a/sys/powerpc/booke/copyinout.c +++ b/sys/powerpc/booke/copyinout.c @@ -87,7 +87,7 @@ copyout(const void *kaddr, void *udaddr, size_t len) if (!is_uaddr(udaddr)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; @@ -109,7 +109,7 @@ copyin(const void *udaddr, void *kaddr, size_t len) if (!is_uaddr(udaddr) || is_uaddr(kaddr)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; @@ -135,7 +135,7 @@ copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) if (!is_uaddr(udaddr) || is_uaddr(kaddr)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; @@ -175,7 +175,7 @@ subyte(void *addr, int byte) if (!is_uaddr(addr)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; @@ -197,7 +197,7 @@ suword(void *addr, long word) if (!is_uaddr(addr)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; @@ -228,7 +228,7 @@ fubyte(const void *addr) if (!is_uaddr(addr)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; @@ -251,7 +251,7 @@ fuword(const void *addr) if (!is_uaddr(addr)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; @@ -288,7 +288,7 @@ casuword(volatile u_long *addr, u_long old, u_long new) if (!((vm_offset_t)addr <= VM_MAXUSER_ADDRESS)) return (EFAULT); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = NULL; diff --git a/sys/powerpc/booke/interrupt.c b/sys/powerpc/booke/interrupt.c index c0bdee1..e268537 100644 --- a/sys/powerpc/booke/interrupt.c +++ b/sys/powerpc/booke/interrupt.c @@ -118,7 +118,7 @@ powerpc_decr_interrupt(struct trapframe *framep) struct thread *td; struct trapframe *oldframe; - td = PCPU_GET(curthread); + td = curthread; critical_enter(); atomic_add_int(&td->td_intr_nesting_level, 1); oldframe = td->td_intr_frame; diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c index a2d0d70..fc506bd 100644 --- a/sys/powerpc/booke/trap.c +++ b/sys/powerpc/booke/trap.c @@ -145,7 +145,7 @@ trap(struct trapframe *frame) PCPU_INC(cnt.v_trap); - td = PCPU_GET(curthread); + td = curthread; p = td->td_proc; type = frame->exc; @@ -382,7 +382,7 @@ syscall(struct trapframe *frame) struct syscall_args sa; int error; - td = PCPU_GET(curthread); + td = curthread; td->td_frame = frame; error = syscallenter(td, &sa); @@ -480,7 +480,7 @@ badaddr_read(void *addr, size_t size, int *rptr) /* Get rid of any stale machine checks that have been waiting. */ __asm __volatile ("sync; isync"); - td = PCPU_GET(curthread); + td = curthread; if (setfault(env)) { td->td_pcb->pcb_onfault = 0; diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h index 949bbf3..631abd2 100644 --- a/sys/powerpc/include/pcpu.h +++ b/sys/powerpc/include/pcpu.h @@ -135,6 +135,14 @@ struct pmap; #ifdef _KERNEL #define pcpup ((struct pcpu *) powerpc_get_pcpup()) +#ifdef __powerpc64__ +register struct thread *curthread_reg __asm("%r13"); +#else +register struct thread *curthread_reg __asm("%r2"); +#endif +#ifdef AIM /* Book-E not yet adapted */ +#define curthread curthread_reg +#endif #define PCPU_GET(member) (pcpup->pc_ ## member) diff --git a/sys/powerpc/ofw/ofwcall32.S b/sys/powerpc/ofw/ofwcall32.S index 06cc105..d2ba70f 100644 --- a/sys/powerpc/ofw/ofwcall32.S +++ b/sys/powerpc/ofw/ofwcall32.S @@ -87,10 +87,11 @@ ASENTRY(ofwcall) * later. */ mr %r5,%r1 - lis %r1,(ofwstk+OFWSTKSZ-16)@ha - addi %r1,%r1,(ofwstk+OFWSTKSZ-16)@l - stw %r5,8(%r1) /* Save real stack pointer */ - stw %r6,12(%r1) /* Save old MSR */ + lis %r1,(ofwstk+OFWSTKSZ-32)@ha + addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l + stw %r5,20(%r1) /* Save real stack pointer */ + stw %r2,24(%r1) /* Save curthread */ + stw %r6,28(%r1) /* Save old MSR */ li %r5,0 stw %r5,4(%r1) stw %r5,0(%r1) @@ -100,8 +101,9 @@ ASENTRY(ofwcall) bctrl /* Reload stack pointer and MSR from the OFW stack */ - lwz %r6,12(%r1) - lwz %r1,8(%r1) + lwz %r6,28(%r1) + lwz %r2,24(%r1) + lwz %r1,20(%r1) /* Now set the real MSR */ mtmsr %r6 diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c index 62a97e9..3563376 100644 --- a/sys/powerpc/powerpc/mp_machdep.c +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -96,10 +96,6 @@ machdep_ap_bootstrap(void) printf("SMP: AP CPU #%d launched\n", PCPU_GET(cpuid)); mtx_unlock_spin(&ap_boot_mtx); - /* Initialize curthread */ - PCPU_SET(curthread, PCPU_GET(idlethread)); - PCPU_SET(curpcb, curthread->td_pcb); - /* Start per-CPU event timers. */ cpu_initclocks_ap(); -- cgit v1.1 From dc0788739aaaf15b40f6d2fded382c167e26133d Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 02:30:02 +0000 Subject: - Move all USB device ID arrays into so-called sections, sorted according to the mode which they support: host, device or dual mode - Add generic tool to extract these data: tools/bus_autoconf Discussed with: imp Suggested by: Robert Millan PR: misc/157903 MFC after: 14 days --- sys/dev/sound/usb/uaudio.c | 9 + sys/dev/usb/input/atp.c | 2 +- sys/dev/usb/input/uhid.c | 28 +- sys/dev/usb/net/if_aue.c | 2 +- sys/dev/usb/net/if_axe.c | 2 +- sys/dev/usb/net/if_cdce.c | 10 +- sys/dev/usb/net/if_cue.c | 2 +- sys/dev/usb/net/if_ipheth.c | 2 +- sys/dev/usb/net/if_kue.c | 2 +- sys/dev/usb/net/if_mos.c | 2 +- sys/dev/usb/net/if_rue.c | 2 +- sys/dev/usb/net/if_udav.c | 2 +- sys/dev/usb/net/uhso.c | 2 +- sys/dev/usb/serial/u3g.c | 2 +- sys/dev/usb/serial/uark.c | 2 +- sys/dev/usb/serial/ubsa.c | 2 +- sys/dev/usb/serial/uchcom.c | 2 +- sys/dev/usb/serial/ucycom.c | 2 +- sys/dev/usb/serial/uftdi.c | 2 +- sys/dev/usb/serial/ugensa.c | 2 +- sys/dev/usb/serial/uipaq.c | 2 +- sys/dev/usb/serial/ulpt.c | 35 ++- sys/dev/usb/serial/umcs.c | 2 +- sys/dev/usb/serial/umct.c | 2 +- sys/dev/usb/serial/umodem.c | 2 +- sys/dev/usb/serial/umoscom.c | 2 +- sys/dev/usb/serial/uplcom.c | 2 +- sys/dev/usb/serial/uslcom.c | 2 +- sys/dev/usb/serial/uvisor.c | 2 +- sys/dev/usb/serial/uvscom.c | 2 +- sys/dev/usb/storage/umass.c | 5 + sys/dev/usb/usbdi.h | 12 + sys/dev/usb/wlan/if_rum.c | 2 +- sys/dev/usb/wlan/if_run.c | 2 +- sys/dev/usb/wlan/if_uath.c | 2 +- sys/dev/usb/wlan/if_upgt.c | 4 +- sys/dev/usb/wlan/if_ural.c | 2 +- sys/dev/usb/wlan/if_urtw.c | 2 +- sys/dev/usb/wlan/if_zyd.c | 2 +- sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c | 4 +- sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c | 2 +- tools/tools/bus_autoconf/Makefile | 43 +++ tools/tools/bus_autoconf/bus_autoconf.c | 321 +++++++++++++++++++++ tools/tools/bus_autoconf/bus_autoconf.h | 83 ++++++ tools/tools/bus_autoconf/bus_autoconf.sh | 64 ++++ 45 files changed, 623 insertions(+), 61 deletions(-) create mode 100644 tools/tools/bus_autoconf/Makefile create mode 100644 tools/tools/bus_autoconf/bus_autoconf.c create mode 100644 tools/tools/bus_autoconf/bus_autoconf.h create mode 100644 tools/tools/bus_autoconf/bus_autoconf.sh diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index 4f8670a..f40ada7 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -531,6 +531,15 @@ static driver_t uaudio_driver = { .size = sizeof(struct uaudio_softc), }; +static const STRUCT_USB_HOST_ID __used uaudio_devs[] = { + /* Generic USB audio class match */ + {USB_IFACE_CLASS(UICLASS_AUDIO), + USB_IFACE_SUBCLASS(UISUBCLASS_AUDIOCONTROL),}, + /* Generic USB MIDI class match */ + {USB_IFACE_CLASS(UICLASS_AUDIO), + USB_IFACE_SUBCLASS(UISUBCLASS_MIDISTREAM),}, +}; + static int uaudio_probe(device_t dev) { diff --git a/sys/dev/usb/input/atp.c b/sys/dev/usb/input/atp.c index fab60a2..9a17950 100644 --- a/sys/dev/usb/input/atp.c +++ b/sys/dev/usb/input/atp.c @@ -240,7 +240,7 @@ struct atp_dev_params { }, }; -static const struct usb_device_id atp_devs[] = { +static const STRUCT_USB_HOST_ID atp_devs[] = { /* Core Duo MacBook & MacBook Pro */ { USB_VPI(USB_VENDOR_APPLE, 0x0217, ATP_DEV_PARAMS_0) }, { USB_VPI(USB_VENDOR_APPLE, 0x0218, ATP_DEV_PARAMS_0) }, diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c index a7fd899..1da1203 100644 --- a/sys/dev/usb/input/uhid.c +++ b/sys/dev/usb/input/uhid.c @@ -607,29 +607,33 @@ uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, return (error); } +static const STRUCT_USB_HOST_ID uhid_devs[] = { + /* generic HID class */ + {USB_IFACE_CLASS(UICLASS_HID),}, + /* the Xbox 360 gamepad doesn't use the HID class */ + {USB_IFACE_CLASS(UICLASS_VENDOR), + USB_IFACE_SUBCLASS(UISUBCLASS_XBOX360_CONTROLLER), + USB_IFACE_PROTOCOL(UIPROTO_XBOX360_GAMEPAD),}, +}; + static int uhid_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); + int error; DPRINTFN(11, "\n"); - if (uaa->usb_mode != USB_MODE_HOST) { + if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); - } - if (uaa->info.bInterfaceClass != UICLASS_HID) { - /* the Xbox 360 gamepad doesn't use the HID class */ + error = usbd_lookup_id_by_uaa(uhid_devs, sizeof(uhid_devs), uaa); + if (error) + return (error); - if ((uaa->info.bInterfaceClass != UICLASS_VENDOR) || - (uaa->info.bInterfaceSubClass != UISUBCLASS_XBOX360_CONTROLLER) || - (uaa->info.bInterfaceProtocol != UIPROTO_XBOX360_GAMEPAD)) { - return (ENXIO); - } - } - if (usb_test_quirk(uaa, UQ_HID_IGNORE)) { + if (usb_test_quirk(uaa, UQ_HID_IGNORE)) return (ENXIO); - } + return (BUS_PROBE_GENERIC); } diff --git a/sys/dev/usb/net/if_aue.c b/sys/dev/usb/net/if_aue.c index 3716844..71871de 100644 --- a/sys/dev/usb/net/if_aue.c +++ b/sys/dev/usb/net/if_aue.c @@ -110,7 +110,7 @@ SYSCTL_INT(_hw_usb_aue, OID_AUTO, debug, CTLFLAG_RW, &aue_debug, 0, /* * Various supported device vendors/products. */ -static const struct usb_device_id aue_devs[] = { +static const STRUCT_USB_HOST_ID aue_devs[] = { #define AUE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } AUE_DEV(3COM, 3C460B, AUE_FLAG_PII), AUE_DEV(ABOCOM, DSB650TX_PNA, 0), diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c index 00d1c0b..5c94e91 100644 --- a/sys/dev/usb/net/if_axe.c +++ b/sys/dev/usb/net/if_axe.c @@ -133,7 +133,7 @@ SYSCTL_INT(_hw_usb_axe, OID_AUTO, debug, CTLFLAG_RW, &axe_debug, 0, /* * Various supported device vendors/products. */ -static const struct usb_device_id axe_devs[] = { +static const STRUCT_USB_HOST_ID axe_devs[] = { #define AXE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } AXE_DEV(ABOCOM, UF200, 0), AXE_DEV(ACERCM, EP1427X2, 0), diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c index b48e79d..12e6f67 100644 --- a/sys/dev/usb/net/if_cdce.c +++ b/sys/dev/usb/net/if_cdce.c @@ -263,7 +263,7 @@ static const struct usb_ether_methods cdce_ue_methods = { .ue_setpromisc = cdce_setpromisc, }; -static const struct usb_device_id cdce_devs[] = { +static const STRUCT_USB_HOST_ID cdce_host_devs[] = { {USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)}, {USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)}, {USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)}, @@ -277,7 +277,9 @@ static const struct usb_device_id cdce_devs[] = { {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, +}; +static const STRUCT_USB_DUAL_ID cdce_dual_devs[] = { {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)}, {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)}, {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_NETWORK_CONTROL_MODEL, 0)}, @@ -472,8 +474,12 @@ static int cdce_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); + int error; - return (usbd_lookup_id_by_uaa(cdce_devs, sizeof(cdce_devs), uaa)); + error = usbd_lookup_id_by_uaa(cdce_host_devs, sizeof(cdce_host_devs), uaa); + if (error) + error = usbd_lookup_id_by_uaa(cdce_dual_devs, sizeof(cdce_dual_devs), uaa); + return (error); } static void diff --git a/sys/dev/usb/net/if_cue.c b/sys/dev/usb/net/if_cue.c index fae8f70..90a18f3 100644 --- a/sys/dev/usb/net/if_cue.c +++ b/sys/dev/usb/net/if_cue.c @@ -88,7 +88,7 @@ __FBSDID("$FreeBSD$"); /* Belkin F5U111 adapter covered by NETMATE entry */ -static const struct usb_device_id cue_devs[] = { +static const STRUCT_USB_HOST_ID cue_devs[] = { #define CUE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } CUE_DEV(CATC, NETMATE), CUE_DEV(CATC, NETMATE2), diff --git a/sys/dev/usb/net/if_ipheth.c b/sys/dev/usb/net/if_ipheth.c index c8a348a..d666835 100644 --- a/sys/dev/usb/net/if_ipheth.c +++ b/sys/dev/usb/net/if_ipheth.c @@ -148,7 +148,7 @@ static const struct usb_ether_methods ipheth_ue_methods = { USB_IFACE_CLASS(c), USB_IFACE_SUBCLASS(sc), \ USB_IFACE_PROTOCOL(pt) -static const struct usb_device_id ipheth_devs[] = { +static const STRUCT_USB_HOST_ID ipheth_devs[] = { {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO)}, diff --git a/sys/dev/usb/net/if_kue.c b/sys/dev/usb/net/if_kue.c index 6c97d28..5480a5d 100644 --- a/sys/dev/usb/net/if_kue.c +++ b/sys/dev/usb/net/if_kue.c @@ -100,7 +100,7 @@ __FBSDID("$FreeBSD$"); /* * Various supported device vendors/products. */ -static const struct usb_device_id kue_devs[] = { +static const STRUCT_USB_HOST_ID kue_devs[] = { #define KUE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } KUE_DEV(3COM, 3C19250), KUE_DEV(3COM, 3C460), diff --git a/sys/dev/usb/net/if_mos.c b/sys/dev/usb/net/if_mos.c index a0e453c..1e884f9 100644 --- a/sys/dev/usb/net/if_mos.c +++ b/sys/dev/usb/net/if_mos.c @@ -146,7 +146,7 @@ SYSCTL_INT(_hw_usb_mos, OID_AUTO, debug, CTLFLAG_RW, &mos_debug, 0, /* Various supported device vendors/products. */ -static const struct usb_device_id mos_devs[] = { +static const STRUCT_USB_HOST_ID mos_devs[] = { {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730, MCS7730)}, {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830, MCS7830)}, {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030, MCS7830)}, diff --git a/sys/dev/usb/net/if_rue.c b/sys/dev/usb/net/if_rue.c index 1dadd57..afd2f4d 100644 --- a/sys/dev/usb/net/if_rue.c +++ b/sys/dev/usb/net/if_rue.c @@ -108,7 +108,7 @@ SYSCTL_INT(_hw_usb_rue, OID_AUTO, debug, CTLFLAG_RW, * Various supported device vendors/products. */ -static const struct usb_device_id rue_devs[] = { +static const STRUCT_USB_HOST_ID rue_devs[] = { {USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX, 0)}, {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USBKR100, 0)}, {USB_VPI(USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01, 0)}, diff --git a/sys/dev/usb/net/if_udav.c b/sys/dev/usb/net/if_udav.c index a6598ef..d2cceaa 100644 --- a/sys/dev/usb/net/if_udav.c +++ b/sys/dev/usb/net/if_udav.c @@ -199,7 +199,7 @@ SYSCTL_INT(_hw_usb_udav, OID_AUTO, debug, CTLFLAG_RW, &udav_debug, 0, #define UDAV_CLRBIT(sc, reg, x) \ udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x)) -static const struct usb_device_id udav_devs[] = { +static const STRUCT_USB_HOST_ID udav_devs[] = { /* ShanTou DM9601 USB NIC */ {USB_VPI(USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_DM9601, 0)}, /* ShanTou ST268 USB NIC */ diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c index 06ac416..ab13093 100644 --- a/sys/dev/usb/net/uhso.c +++ b/sys/dev/usb/net/uhso.c @@ -247,7 +247,7 @@ static char *uhso_port_type_sysctl[] = { /* ifnet device unit allocations */ static struct unrhdr *uhso_ifnet_unit = NULL; -static const struct usb_device_id uhso_devs[] = { +static const STRUCT_USB_HOST_ID uhso_devs[] = { #define UHSO_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } /* Option GlobeSurfer iCON 7.2 */ UHSO_DEV(OPTION, GSICON72, UHSO_STATIC_IFACE), diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c index c332bfb..31e8e11 100644 --- a/sys/dev/usb/serial/u3g.c +++ b/sys/dev/usb/serial/u3g.c @@ -182,7 +182,7 @@ MODULE_DEPEND(u3g, ucom, 1, 1, 1); MODULE_DEPEND(u3g, usb, 1, 1, 1); MODULE_VERSION(u3g, 1); -static const struct usb_device_id u3g_devs[] = { +static const STRUCT_USB_HOST_ID u3g_devs[] = { #define U3G_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } U3G_DEV(ACERP, H10, 0), U3G_DEV(AIRPLUS, MCD650, 0), diff --git a/sys/dev/usb/serial/uark.c b/sys/dev/usb/serial/uark.c index 75100f2..2c3943d 100644 --- a/sys/dev/usb/serial/uark.c +++ b/sys/dev/usb/serial/uark.c @@ -170,7 +170,7 @@ MODULE_DEPEND(uark, ucom, 1, 1, 1); MODULE_DEPEND(uark, usb, 1, 1, 1); MODULE_VERSION(uark, 1); -static const struct usb_device_id uark_devs[] = { +static const STRUCT_USB_HOST_ID uark_devs[] = { {USB_VPI(USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116, 0)}, }; diff --git a/sys/dev/usb/serial/ubsa.c b/sys/dev/usb/serial/ubsa.c index 1a5a75a..6afe05b 100644 --- a/sys/dev/usb/serial/ubsa.c +++ b/sys/dev/usb/serial/ubsa.c @@ -239,7 +239,7 @@ static const struct ucom_callback ubsa_callback = { .ucom_poll = &ubsa_poll, }; -static const struct usb_device_id ubsa_devs[] = { +static const STRUCT_USB_HOST_ID ubsa_devs[] = { /* AnyData ADU-500A */ {USB_VPI(USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_500A, 0)}, /* AnyData ADU-E100A/H */ diff --git a/sys/dev/usb/serial/uchcom.c b/sys/dev/usb/serial/uchcom.c index 60fa9e0..3f69c4d 100644 --- a/sys/dev/usb/serial/uchcom.c +++ b/sys/dev/usb/serial/uchcom.c @@ -204,7 +204,7 @@ static const struct uchcom_divider_record dividers[] = #define NUM_DIVIDERS (sizeof (dividers) / sizeof (dividers[0])) -static const struct usb_device_id uchcom_devs[] = { +static const STRUCT_USB_HOST_ID uchcom_devs[] = { {USB_VPI(USB_VENDOR_WCH, USB_PRODUCT_WCH_CH341SER, 0)}, {USB_VPI(USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER, 0)}, }; diff --git a/sys/dev/usb/serial/ucycom.c b/sys/dev/usb/serial/ucycom.c index a58398a..8fef219 100644 --- a/sys/dev/usb/serial/ucycom.c +++ b/sys/dev/usb/serial/ucycom.c @@ -180,7 +180,7 @@ MODULE_VERSION(ucycom, 1); /* * Supported devices */ -static const struct usb_device_id ucycom_devs[] = { +static const STRUCT_USB_HOST_ID ucycom_devs[] = { {USB_VPI(USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE, MODEL_CY7C64013)}, }; diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c index b196862..1c88063 100644 --- a/sys/dev/usb/serial/uftdi.c +++ b/sys/dev/usb/serial/uftdi.c @@ -206,7 +206,7 @@ MODULE_DEPEND(uftdi, ucom, 1, 1, 1); MODULE_DEPEND(uftdi, usb, 1, 1, 1); MODULE_VERSION(uftdi, 1); -static struct usb_device_id uftdi_devs[] = { +static STRUCT_USB_HOST_ID uftdi_devs[] = { #define UFTDI_DEV(v,p,t) \ { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, UFTDI_TYPE_##t) } UFTDI_DEV(ATMEL, STK541, 8U232AM), diff --git a/sys/dev/usb/serial/ugensa.c b/sys/dev/usb/serial/ugensa.c index 0c2f2c4..6b0955e 100644 --- a/sys/dev/usb/serial/ugensa.c +++ b/sys/dev/usb/serial/ugensa.c @@ -154,7 +154,7 @@ MODULE_DEPEND(ugensa, ucom, 1, 1, 1); MODULE_DEPEND(ugensa, usb, 1, 1, 1); MODULE_VERSION(ugensa, 1); -static const struct usb_device_id ugensa_devs[] = { +static const STRUCT_USB_HOST_ID ugensa_devs[] = { {USB_VPI(USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220, 0)}, {USB_VPI(USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1, 0)}, {USB_VPI(USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_CDMA_MSM_K, 0)}, diff --git a/sys/dev/usb/serial/uipaq.c b/sys/dev/usb/serial/uipaq.c index 6f96164..d038e17 100644 --- a/sys/dev/usb/serial/uipaq.c +++ b/sys/dev/usb/serial/uipaq.c @@ -153,7 +153,7 @@ static const struct ucom_callback uipaq_callback = { * support the same hardware. Numeric values are used where no usbdevs * entries exist. */ -static const struct usb_device_id uipaq_devs[] = { +static const STRUCT_USB_HOST_ID uipaq_devs[] = { /* Socket USB Sync */ {USB_VPI(0x0104, 0x00be, 0)}, /* USB Sync 0301 */ diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c index ec1aa24..def2ae5 100644 --- a/sys/dev/usb/serial/ulpt.c +++ b/sys/dev/usb/serial/ulpt.c @@ -483,24 +483,39 @@ ulpt_ioctl(struct usb_fifo *fifo, u_long cmd, void *data, return (ENODEV); } +static const STRUCT_USB_HOST_ID ulpt_devs[] = { + /* Uni-directional USB printer */ + {USB_IFACE_CLASS(UICLASS_PRINTER), + USB_IFACE_SUBCLASS(UISUBCLASS_PRINTER), + USB_IFACE_PROTOCOL(UIPROTO_PRINTER_UNI)}, + + /* Bi-directional USB printer */ + {USB_IFACE_CLASS(UICLASS_PRINTER), + USB_IFACE_SUBCLASS(UISUBCLASS_PRINTER), + USB_IFACE_PROTOCOL(UIPROTO_PRINTER_BI)}, + + /* 1284 USB printer */ + {USB_IFACE_CLASS(UICLASS_PRINTER), + USB_IFACE_SUBCLASS(UISUBCLASS_PRINTER), + USB_IFACE_PROTOCOL(UIPROTO_PRINTER_1284)}, +}; + static int ulpt_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); + int error; DPRINTFN(11, "\n"); - if (uaa->usb_mode != USB_MODE_HOST) { + if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); - } - if ((uaa->info.bInterfaceClass == UICLASS_PRINTER) && - (uaa->info.bInterfaceSubClass == UISUBCLASS_PRINTER) && - ((uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_UNI) || - (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_BI) || - (uaa->info.bInterfaceProtocol == UIPROTO_PRINTER_1284))) { - return (0); - } - return (ENXIO); + + error = usbd_lookup_id_by_uaa(ulpt_devs, sizeof(ulpt_devs), uaa); + if (error) + return (error); + + return (BUS_PROBE_GENERIC); } static int diff --git a/sys/dev/usb/serial/umcs.c b/sys/dev/usb/serial/umcs.c index c74044e..94ed4d9 100644 --- a/sys/dev/usb/serial/umcs.c +++ b/sys/dev/usb/serial/umcs.c @@ -253,7 +253,7 @@ static struct ucom_callback umcs7840_callback = { .ucom_poll = &umcs7840_poll, }; -static const struct usb_device_id umcs7840_devs[] = { +static const STRUCT_USB_HOST_ID umcs7840_devs[] = { {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7820, 0)}, {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7840, 0)}, }; diff --git a/sys/dev/usb/serial/umct.c b/sys/dev/usb/serial/umct.c index 39dc9d7..16dd4a1 100644 --- a/sys/dev/usb/serial/umct.c +++ b/sys/dev/usb/serial/umct.c @@ -192,7 +192,7 @@ static const struct ucom_callback umct_callback = { .ucom_poll = &umct_poll, }; -static const struct usb_device_id umct_devs[] = { +static const STRUCT_USB_HOST_ID umct_devs[] = { {USB_VPI(USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232, 0)}, {USB_VPI(USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232, 0)}, {USB_VPI(USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232, 0)}, diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c index c6d517b..92bfe93 100644 --- a/sys/dev/usb/serial/umodem.c +++ b/sys/dev/usb/serial/umodem.c @@ -123,7 +123,7 @@ SYSCTL_INT(_hw_usb_umodem, OID_AUTO, debug, CTLFLAG_RW, &umodem_debug, 0, "Debug level"); #endif -static const struct usb_device_id umodem_devs[] = { +static const STRUCT_USB_HOST_ID umodem_devs[] = { /* Generic Modem class match */ {USB_IFACE_CLASS(UICLASS_CDC), USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL), diff --git a/sys/dev/usb/serial/umoscom.c b/sys/dev/usb/serial/umoscom.c index 4ab6cc0..c346ae6 100644 --- a/sys/dev/usb/serial/umoscom.c +++ b/sys/dev/usb/serial/umoscom.c @@ -280,7 +280,7 @@ MODULE_DEPEND(umoscom, ucom, 1, 1, 1); MODULE_DEPEND(umoscom, usb, 1, 1, 1); MODULE_VERSION(umoscom, 1); -static const struct usb_device_id umoscom_devs[] = { +static const STRUCT_USB_HOST_ID umoscom_devs[] = { {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7703, 0)} }; diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c index 108ee7b..4af0537 100644 --- a/sys/dev/usb/serial/uplcom.c +++ b/sys/dev/usb/serial/uplcom.c @@ -247,7 +247,7 @@ static struct ucom_callback uplcom_callback = { #define UPLCOM_DEV(v,p) \ { USB_VENDOR(USB_VENDOR_##v), USB_PRODUCT(USB_PRODUCT_##v##_##p) } -static const struct usb_device_id uplcom_devs[] = { +static const STRUCT_USB_HOST_ID uplcom_devs[] = { UPLCOM_DEV(ACERP, S81), /* BenQ S81 phone */ UPLCOM_DEV(ADLINK, ND6530), /* ADLINK ND-6530 USB-Serial */ UPLCOM_DEV(ALCATEL, OT535), /* Alcatel One Touch 535/735 */ diff --git a/sys/dev/usb/serial/uslcom.c b/sys/dev/usb/serial/uslcom.c index 1357c8d..6eaec83 100644 --- a/sys/dev/usb/serial/uslcom.c +++ b/sys/dev/usb/serial/uslcom.c @@ -173,7 +173,7 @@ static struct ucom_callback uslcom_callback = { .ucom_poll = &uslcom_poll, }; -static const struct usb_device_id uslcom_devs[] = { +static const STRUCT_USB_HOST_ID uslcom_devs[] = { #define USLCOM_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } USLCOM_DEV(BALTECH, CARDREADER), USLCOM_DEV(CLIPSAL, 5500PCU), diff --git a/sys/dev/usb/serial/uvisor.c b/sys/dev/usb/serial/uvisor.c index 3efef5d..976ea19 100644 --- a/sys/dev/usb/serial/uvisor.c +++ b/sys/dev/usb/serial/uvisor.c @@ -253,7 +253,7 @@ MODULE_DEPEND(uvisor, ucom, 1, 1, 1); MODULE_DEPEND(uvisor, usb, 1, 1, 1); MODULE_VERSION(uvisor, 1); -static const struct usb_device_id uvisor_devs[] = { +static const STRUCT_USB_HOST_ID uvisor_devs[] = { #define UVISOR_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } UVISOR_DEV(ACEECA, MEZ1000, UVISOR_FLAG_PALM4), UVISOR_DEV(ALPHASMART, DANA_SYNC, UVISOR_FLAG_PALM4), diff --git a/sys/dev/usb/serial/uvscom.c b/sys/dev/usb/serial/uvscom.c index d883190..52e02ad 100644 --- a/sys/dev/usb/serial/uvscom.c +++ b/sys/dev/usb/serial/uvscom.c @@ -233,7 +233,7 @@ static const struct ucom_callback uvscom_callback = { .ucom_poll = &uvscom_poll, }; -static const struct usb_device_id uvscom_devs[] = { +static const STRUCT_USB_HOST_ID uvscom_devs[] = { /* SUNTAC U-Cable type A4 */ {USB_VPI(USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4, 0)}, /* SUNTAC U-Cable type D2 */ diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c index 158d843..9292c84 100644 --- a/sys/dev/usb/storage/umass.c +++ b/sys/dev/usb/storage/umass.c @@ -721,6 +721,11 @@ MODULE_VERSION(umass, 1); * USB device probe/attach/detach */ +static const STRUCT_USB_HOST_ID __used umass_devs[] = { + /* generic mass storage class */ + {USB_IFACE_CLASS(UICLASS_MASS),}, +}; + static uint16_t umass_get_proto(struct usb_interface *iface) { diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 91cd3fa..a216879 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -228,6 +228,18 @@ struct usb_config { }; /* + * Use these macro when defining USB device ID arrays if you want to + * have your driver module automatically loaded in host, device or + * both modes respectivly: + */ +#define STRUCT_USB_HOST_ID \ + struct usb_device_id __section("usb_host_id") +#define STRUCT_USB_DEVICE_ID \ + struct usb_device_id __section("usb_device_id") +#define STRUCT_USB_DUAL_ID \ + struct usb_device_id __section("usb_dual_id") + +/* * The following structure is used when looking up an USB driver for * an USB device. It is inspired by the Linux structure called * "usb_device_id". diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index 63b314d..5a69792 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -85,7 +85,7 @@ SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RW, &rum_debug, 0, "Debug level"); #endif -static const struct usb_device_id rum_devs[] = { +static const STRUCT_USB_HOST_ID rum_devs[] = { #define RUM_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } RUM_DEV(ABOCOM, HWU54DM), RUM_DEV(ABOCOM, RT2573_2), diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 2cd147c..47823b9 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -96,7 +96,7 @@ SYSCTL_INT(_hw_usb_run, OID_AUTO, debug, CTLFLAG_RW, &run_debug, 0, */ #define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ) -static const struct usb_device_id run_devs[] = { +static const STRUCT_USB_HOST_ID run_devs[] = { #define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } RUN_DEV(ABOCOM, RT2770), RUN_DEV(ABOCOM, RT2870), diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 35202a9..baff5de 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -167,7 +167,7 @@ enum { (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))) /* recognized device vendors/products */ -static const struct usb_device_id uath_devs[] = { +static const STRUCT_USB_HOST_ID uath_devs[] = { #define UATH_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } UATH_DEV(ACCTON, SMCWUSBG), UATH_DEV(ACCTON, SMCWUSBTG2), diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index d704cec..b9381a2 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -170,7 +170,7 @@ static int upgt_tx_start(struct upgt_softc *, struct mbuf *, static const char *upgt_fwname = "upgt-gw3887"; -static const struct usb_device_id upgt_devs_2[] = { +static const STRUCT_USB_HOST_ID upgt_devs[] = { #define UPGT_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } /* version 2 devices */ UPGT_DEV(ACCTON, PRISM_GT), @@ -236,7 +236,7 @@ upgt_match(device_t dev) if (uaa->info.bIfaceIndex != UPGT_IFACE_INDEX) return (ENXIO); - return (usbd_lookup_id_by_uaa(upgt_devs_2, sizeof(upgt_devs_2), uaa)); + return (usbd_lookup_id_by_uaa(upgt_devs, sizeof(upgt_devs), uaa)); } static int diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c index 65d974a..048392d 100644 --- a/sys/dev/usb/wlan/if_ural.c +++ b/sys/dev/usb/wlan/if_ural.c @@ -91,7 +91,7 @@ SYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0, ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0) /* various supported device vendors/products */ -static const struct usb_device_id ural_devs[] = { +static const STRUCT_USB_HOST_ID ural_devs[] = { #define URAL_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } URAL_DEV(ASUS, WL167G), URAL_DEV(ASUS, RT2570), diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index 7805c2d..6ae7e16 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -102,7 +102,7 @@ TUNABLE_INT("hw.usb.urtw.preamble_mode", &urtw_preamble_mode); { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, URTW_REV_RTL8187L) } #define URTW_REV_RTL8187B 0 #define URTW_REV_RTL8187L 1 -static const struct usb_device_id urtw_devs[] = { +static const STRUCT_USB_HOST_ID urtw_devs[] = { URTW_DEV_B(NETGEAR, WG111V3), URTW_DEV_B(REALTEK, RTL8187B_0), URTW_DEV_B(REALTEK, RTL8187B_1), diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index 43ec6ca..f8d905e 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -200,7 +200,7 @@ static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB; { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, ZYD_ZD1211) } #define ZYD_ZD1211B_DEV(v,p) \ { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, ZYD_ZD1211B) } -static const struct usb_device_id zyd_devs[] = { +static const STRUCT_USB_HOST_ID zyd_devs[] = { /* ZYD_ZD1211 */ ZYD_ZD1211_DEV(3COM2, 3CRUSB10075), ZYD_ZD1211_DEV(ABOCOM, WL54), diff --git a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c index a13ef4d..d3f8fd3 100644 --- a/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c +++ b/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c @@ -382,14 +382,14 @@ static const struct usb_config ubt_config[UBT_N_TRANSFER] = * where VENDOR_ID and PRODUCT_ID are hex numbers. */ -static const struct usb_device_id ubt_ignore_devs[] = +static const STRUCT_USB_HOST_ID ubt_ignore_devs[] = { /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */ { USB_VPI(USB_VENDOR_AVM, 0x2200, 0) }, }; /* List of supported bluetooth devices */ -static const struct usb_device_id ubt_devs[] = +static const STRUCT_USB_HOST_ID ubt_devs[] = { /* Generic Bluetooth class devices */ { USB_IFACE_CLASS(UDCLASS_WIRELESS), diff --git a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c b/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c index 3d8a05e..da00e05 100644 --- a/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c +++ b/sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c @@ -180,7 +180,7 @@ MODULE_DEPEND(ubtbcmfw, usb, 1, 1, 1); static int ubtbcmfw_probe(device_t dev) { - const struct usb_device_id devs[] = { + static const STRUCT_USB_HOST_ID devs[] = { /* Broadcom BCM2033 devices only */ { USB_VPI(USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033, 0) }, }; diff --git a/tools/tools/bus_autoconf/Makefile b/tools/tools/bus_autoconf/Makefile new file mode 100644 index 0000000..c2f1b13 --- /dev/null +++ b/tools/tools/bus_autoconf/Makefile @@ -0,0 +1,43 @@ +# $FreeBSD$ +# +# Copyright (c) 2011 Hans Petter Selasky. 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. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +# + +# +# Example on how to use: +# +# make clean all install +# +# ./bus_autoconf.sh /boot/kernel/*.ko | less +# + +PROG= bus_autoconf +MAN= +BINDIR?= /usr/local/bin + +SRCS= bus_autoconf.c + +WARNS= 6 + +.include diff --git a/tools/tools/bus_autoconf/bus_autoconf.c b/tools/tools/bus_autoconf/bus_autoconf.c new file mode 100644 index 0000000..68688af --- /dev/null +++ b/tools/tools/bus_autoconf/bus_autoconf.c @@ -0,0 +1,321 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * Disclaimer: This utility and format is subject to change and not a + * comitted interface. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bus_autoconf.h" + +static char *type; +static char *file_name; +static char *module; +static const char *mode; + +static int +usb_compare(const void *_a, const void *_b) +{ + const struct usb_device_id *a = _a; + const struct usb_device_id *b = _b; + + if (a->idVendor > b->idVendor) + return (1); + if (a->idVendor < b->idVendor) + return (-1); + if (a->idProduct > b->idProduct) + return (1); + if (a->idProduct < b->idProduct) + return (-1); + if (a->bDeviceClass > b->bDeviceClass) + return (1); + if (a->bDeviceClass < b->bDeviceClass) + return (-1); + if (a->bDeviceSubClass > b->bDeviceSubClass) + return (1); + if (a->bDeviceSubClass < b->bDeviceSubClass) + return (-1); + if (a->bDeviceProtocol > b->bDeviceProtocol) + return (1); + if (a->bDeviceProtocol < b->bDeviceProtocol) + return (-1); + if (a->bInterfaceClass > b->bInterfaceClass) + return (1); + if (a->bInterfaceClass < b->bInterfaceClass) + return (-1); + if (a->bInterfaceSubClass > b->bInterfaceSubClass) + return (1); + if (a->bInterfaceSubClass < b->bInterfaceSubClass) + return (-1); + if (a->bInterfaceProtocol > b->bInterfaceProtocol) + return (1); + if (a->bInterfaceProtocol < b->bInterfaceProtocol) + return (-1); + + return (0); +} + +static void +usb_sort(struct usb_device_id *id, uint32_t nid) +{ + qsort(id, nid, sizeof(*id), &usb_compare); +} + +struct usb_info { + uint8_t is_iface; + uint8_t is_any; + uint8_t is_vp; + uint8_t is_dev; +}; + +static void +usb_dump_sub(struct usb_device_id *id, struct usb_info *pinfo) +{ +#if USB_HAVE_COMPAT_LINUX + if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) + id->match_flag_vendor = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) + id->match_flag_product = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) + id->match_flag_dev_lo = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) + id->match_flag_dev_hi = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) + id->match_flag_dev_class = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) + id->match_flag_dev_subclass = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) + id->match_flag_dev_protocol = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) + id->match_flag_int_class = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) + id->match_flag_int_subclass = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) + id->match_flag_int_protocol = 1; +#endif + + pinfo->is_iface = id->match_flag_int_class | + id->match_flag_int_protocol | + id->match_flag_int_subclass; + + pinfo->is_dev = id->match_flag_dev_class | + id->match_flag_dev_subclass; + + pinfo->is_vp = id->match_flag_vendor | + id->match_flag_product; + + pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface; +} + +static uint32_t +usb_dump(struct usb_device_id *id, uint32_t nid) +{ + uint32_t n = 1; + struct usb_info info; + + usb_dump_sub(id, &info); + + if (info.is_iface) { + printf("nomatch 10 {\n" + " match \"system\" \"USB\";\n" + " match \"subsystem\" \"INTERFACE\";\n" + " match \"mode\" \"%s\";\n", mode); + } else if (info.is_any) { + printf("nomatch 10 {\n" + " match \"system\" \"USB\";\n" + " match \"subsystem\" \"DEVICE\";\n" + " match \"mode\" \"%s\";\n", mode); + } else { + return (n); + } + + if (id->match_flag_vendor) { + printf(" match \"vendor\" \"0x%04x\";\n", + id->idVendor); + } + if (id->match_flag_product) { + uint32_t x; + + if (info.is_any == 1 && info.is_vp == 1) { + /* try to join similar entries */ + while (n < nid) { + usb_dump_sub(id + n, &info); + + if (info.is_any != 1 || info.is_vp != 1) + break; + if (id[n].idVendor != id[0].idVendor) + break; + n++; + } + /* restore infos */ + usb_dump_sub(id, &info); + } + if (n == 1) { + printf(" match \"product\" \"0x%04x\";\n", + id->idProduct); + } else { + printf(" match \"product\" \"("); + + for (x = 0; x != n; x++) { + printf("0x%04x%s", id[x].idProduct, + (x == (n - 1)) ? "" : "|"); + } + + printf(")\";\n"); + } + } + if (id->match_flag_dev_class) { + printf(" match \"devclass\" \"0x%02x\";\n", + id->bDeviceClass); + } + if (id->match_flag_dev_subclass) { + printf(" match \"devsubclass\" \"0x%02x\";\n", + id->bDeviceSubClass); + } + if (id->match_flag_int_class) { + printf(" match \"intclass\" \"0x%02x\";\n", + id->bInterfaceClass); + } + if (id->match_flag_int_subclass) { + printf(" match \"intsubclass\" \"0x%02x\";\n", + id->bInterfaceSubClass); + } + if (id->match_flag_int_protocol) { + printf(" match \"intprotocol\" \"0x%02x\";\n", + id->bInterfaceProtocol); + } + printf(" action \"kldload %s\";\n" + "};\n\n", module); + + return (n); +} + +static void +usb_parse_and_dump(int f, off_t size) +{ + struct usb_device_id *id; + uint32_t nid; + uint32_t x; + + if (size % sizeof(struct usb_device_id)) { + errx(EX_NOINPUT, "Size is not divisible by %d", + (int)sizeof(struct usb_device_id)); + } + lseek(f, 0, SEEK_SET); + + id = malloc(size); + if (id == NULL) { + errx(EX_SOFTWARE, "Out of memory"); + } + if (read(f, id, size) != size) { + err(EX_NOINPUT, "Cannot read all data"); + } + nid = size / sizeof(*id); + + usb_sort(id, nid); + + for (x = 0; x != nid;) + x += usb_dump(id + x, nid - x); + + free(id); +} + +static void +usage(void) +{ + fprintf(stderr, + "bus_autoconf - devd config file generator\n" + " -i \n" + " -m \n" + " -t \n" + " -h show usage\n" + ); + exit(EX_USAGE); +} + +int +main(int argc, char **argv) +{ + const char *params = "i:m:ht:"; + int c; + int f; + off_t off; + + while ((c = getopt(argc, argv, params)) != -1) { + switch (c) { + case 'i': + file_name = optarg; + break; + case 't': + type = optarg; + break; + case 'm': + module = optarg; + break; + default: + usage(); + break; + } + } + + if (type == NULL || module == NULL || file_name == NULL) + usage(); + + f = open(file_name, O_RDONLY); + if (f < 0) + err(EX_NOINPUT, "Cannot open file '%s'", file_name); + + off = lseek(f, 0, SEEK_END); + if (off <= 0) + err(EX_NOINPUT, "Cannot seek to end of file"); + + if (strcmp(type, "usb_host") == 0) { + mode = "host"; + usb_parse_and_dump(f, off); + } else if (strcmp(type, "usb_device") == 0) { + mode = "device"; + usb_parse_and_dump(f, off); + } else if (strcmp(type, "usb_dual") == 0) { + mode = "(host|device)"; + usb_parse_and_dump(f, off); + } else { + err(EX_USAGE, "Unsupported structure type: %s", type); + } + + close(f); + + return (0); +} diff --git a/tools/tools/bus_autoconf/bus_autoconf.h b/tools/tools/bus_autoconf/bus_autoconf.h new file mode 100644 index 0000000..a247109 --- /dev/null +++ b/tools/tools/bus_autoconf/bus_autoconf.h @@ -0,0 +1,83 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef _BUS_AUTOCONF_H_ +#define _BUS_AUTOCONF_H_ + +/* Make sure we get the have compat linux definition. */ +#include + +struct usb_device_id { + + /* Hook for driver specific information */ + unsigned long driver_info; + + /* Used for product specific matches; the BCD range is inclusive */ + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice_lo; + uint16_t bcdDevice_hi; + + /* Used for device class matches */ + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + + /* Used for interface class matches */ + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + + /* Select which fields to match against */ + uint8_t match_flag_vendor:1; + uint8_t match_flag_product:1; + uint8_t match_flag_dev_lo:1; + uint8_t match_flag_dev_hi:1; + uint8_t match_flag_dev_class:1; + uint8_t match_flag_dev_subclass:1; + uint8_t match_flag_dev_protocol:1; + uint8_t match_flag_int_class:1; + uint8_t match_flag_int_subclass:1; + uint8_t match_flag_int_protocol:1; + +#if USB_HAVE_COMPAT_LINUX + /* which fields to match against */ + uint16_t match_flags; +#define USB_DEVICE_ID_MATCH_VENDOR 0x0001 +#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 +#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004 +#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008 +#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010 +#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020 +#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040 +#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 +#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 +#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 +#endif +}; + +#endif /* _BUS_AUTOCONF_H_ */ diff --git a/tools/tools/bus_autoconf/bus_autoconf.sh b/tools/tools/bus_autoconf/bus_autoconf.sh new file mode 100644 index 0000000..4815572 --- /dev/null +++ b/tools/tools/bus_autoconf/bus_autoconf.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# $FreeBSD$ +# +# Copyright (c) 2011 Hans Petter Selasky. 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. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +# + +OS=FreeBSD +DOLLAR=$ + +cat < /dev/null +[ -f ${F}.ids ] && ( +bus_autoconf -i ${F}.ids -t usb_host -m ${H} ; +rm ${F}.ids +) +# USB Device +objcopy -j usb_device_id -O binary ${F} ${F}.ids 2> /dev/null +[ -f ${F}.ids ] && ( +bus_autoconf -i ${F}.ids -t usb_device -m ${H} ; +rm ${F}.ids +) +# USB Dual mode +objcopy -j usb_dual_id -O binary ${F} ${F}.ids 2> /dev/null +[ -f ${F}.ids ] && ( +bus_autoconf -i ${F}.ids -t usb_dual -m ${H} ; +rm ${F}.ids +) +done -- cgit v1.1 From 5d88d5d7feadac7d9ef3004a0506e1fc0f8b4bde Mon Sep 17 00:00:00 2001 From: rodrigc Date: Fri, 24 Jun 2011 02:56:24 +0000 Subject: Bring back synchnet() implementation from older tftp implementation. The synchnet() function was converted to a no-op when the new TFTP implementation was committed to FreeBSD. However, this function, as it was in the older code, is needed in order to synchronize between the tftpd server and tftp clients, which may be buggy. Specifically, we had a buggy TFTP client which would send TFTP ACK packets for non-TFTP packets, which would cause the count of packets to get out of whack, causing transfers to fail with the new TFTPD implementation. Obtained from: Juniper Networks Submitted by: Santhanakrishnan Balraj --- libexec/tftpd/tftp-file.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/libexec/tftpd/tftp-file.c b/libexec/tftpd/tftp-file.c index 1ef8820..6b8fb6e 100644 --- a/libexec/tftpd/tftp-file.c +++ b/libexec/tftpd/tftp-file.c @@ -27,6 +27,8 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #include #include @@ -249,9 +251,34 @@ read_close(void) } +/* When an error has occurred, it is possible that the two sides + * are out of synch. Ie: that what I think is the other side's + * response to packet N is really their response to packet N-1. + * + * So, to try to prevent that, we flush all the input queued up + * for us on the network connection on our host. + * + * We return the number of packets we flushed (mostly for reporting + * when trace is active). + */ + int -synchnet(int peer __unused) +synchnet(int peer) /* socket to flush */ { - - return 0; + int i, j = 0; + char rbuf[MAXPKTSIZE]; + struct sockaddr_storage from; + socklen_t fromlen; + + while (1) { + (void) ioctl(peer, FIONREAD, &i); + if (i) { + j++; + fromlen = sizeof from; + (void) recvfrom(peer, rbuf, sizeof (rbuf), 0, + (struct sockaddr *)&from, &fromlen); + } else { + return(j); + } + } } -- cgit v1.1 From 1621843c39a7f4d45be490ad53fae6944653b975 Mon Sep 17 00:00:00 2001 From: rodrigc Date: Fri, 24 Jun 2011 03:50:54 +0000 Subject: Fixes to newer tftp code in libstand: (1) Coding style changes. (2) If the server does not acknowledge any blocksize option, revert to the default blocksize of 512 bytes. (3) Send ACK if the first packet happens to be the last packet. (4) Do not accept blocksize greater than what was requested. (5) Drop any unwanted OACK received if a tftp transfer is already in progress. (6) Terminate incomplete transfers with a special no-error ERROR packet. Otherwise we rely on the tftp server to time out, which it does eventually, after re-sending the last packet several times and spamming the system log about it every time. This idea is borrowed from the PXE client, which does exactly that. Submitted by: Alexander Kabaev Reviewed and Tested by: Santhanakrishnan Balraj --- lib/libstand/tftp.c | 183 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 132 insertions(+), 51 deletions(-) diff --git a/lib/libstand/tftp.c b/lib/libstand/tftp.c index 54e184c..bf92c04 100644 --- a/lib/libstand/tftp.c +++ b/lib/libstand/tftp.c @@ -64,13 +64,13 @@ struct tftp_handle; static int tftp_open(const char *path, struct open_file *f); static int tftp_close(struct open_file *f); -static void tftp_parse_oack(struct tftp_handle *h, char *buf, size_t len); +static int tftp_parse_oack(struct tftp_handle *h, char *buf, size_t len); static int tftp_read(struct open_file *f, void *buf, size_t size, size_t *resid); static int tftp_write(struct open_file *f, void *buf, size_t size, size_t *resid); static off_t tftp_seek(struct open_file *f, off_t offset, int where); static int tftp_set_blksize(struct tftp_handle *h, const char *str); static int tftp_stat(struct open_file *f, struct stat *sb); -static ssize_t sendrecv_tftp(struct tftp_handle *h, +static ssize_t sendrecv_tftp(struct tftp_handle *h, ssize_t (*sproc)(struct iodesc *, void *, size_t), void *sbuf, size_t ssize, ssize_t (*rproc)(struct tftp_handle *h, void *, ssize_t, time_t, unsigned short *), @@ -93,7 +93,7 @@ static int tftpport = 2000; static int is_open = 0; /* - * The legacy TFTP_BLKSIZE value was 512. + * The legacy TFTP_BLKSIZE value was SEGSIZE(512). * TFTP_REQUESTED_BLKSIZE of 1428 is (Ethernet MTU, less the TFTP, UDP and * IP header lengths). */ @@ -102,7 +102,7 @@ static int is_open = 0; /* * Choose a blksize big enough so we can test with Ethernet * Jumbo frames in the future. - */ + */ #define TFTP_MAX_BLKSIZE 9008 struct tftp_handle { @@ -113,7 +113,7 @@ struct tftp_handle { int off; char *path; /* saved for re-requests */ unsigned int tftp_blksize; - unsigned long tftp_tsize; + unsigned long tftp_tsize; struct { u_char header[HEADER_SIZE]; struct tftphdr t; @@ -121,7 +121,8 @@ struct tftp_handle { } __packed __aligned(4) lastdata; }; -static const int tftperrors[8] = { +#define TFTP_MAX_ERRCODE EOPTNEG +static const int tftperrors[TFTP_MAX_ERRCODE + 1] = { 0, /* ??? */ ENOENT, EPERM, @@ -129,10 +130,57 @@ static const int tftperrors[8] = { EINVAL, /* ??? */ EINVAL, /* ??? */ EEXIST, - EINVAL /* ??? */ + EINVAL, /* ??? */ + EINVAL, /* Option negotiation failed. */ }; -static ssize_t +static int tftp_getnextblock(struct tftp_handle *h); + +/* send error message back. */ +static void +tftp_senderr(struct tftp_handle *h, u_short errcode, const char *msg) +{ + struct { + u_char header[HEADER_SIZE]; + struct tftphdr t; + u_char space[63]; /* +1 from t */ + } __packed __aligned(4) wbuf; + char *wtail; + int len; + + len = strlen(msg); + if (len > sizeof(wbuf.space)) + len = sizeof(wbuf.space); + + wbuf.t.th_opcode = htons((u_short) ERROR); + wbuf.t.th_code = htons(errcode); + + wtail = wbuf.t.th_msg; + bcopy(msg, wtail, len); + wtail[len] = '\0'; + wtail += len + 1; + + sendudp(h->iodesc, &wbuf.t, wtail - (char *) &wbuf.t); +} + +static void +tftp_sendack(struct tftp_handle *h) +{ + struct { + u_char header[HEADER_SIZE]; + struct tftphdr t; + } __packed __aligned(4) wbuf; + char *wtail; + + wbuf.t.th_opcode = htons((u_short) ACK); + wtail = (char *) &wbuf.t.th_block; + wbuf.t.th_block = htons((u_short) h->currblock); + wtail += 2; + + sendudp(h->iodesc, &wbuf.t, wtail - (char *) &wbuf.t); +} + +static ssize_t recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft, unsigned short *rtype) { @@ -170,7 +218,7 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft, return got; } case ERROR: - if ((unsigned) ntohs(t->th_code) >= 8) { + if ((unsigned) ntohs(t->th_code) > TFTP_MAX_ERRCODE) { printf("illegal tftp error %d\n", ntohs(t->th_code)); errno = EIO; } else { @@ -182,14 +230,30 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft, return (-1); case OACK: { struct udphdr *uh; - int tftp_oack_len = len - sizeof(t->th_opcode); - tftp_parse_oack(h, t->th_u.tu_stuff, tftp_oack_len); + int tftp_oack_len; + + /* + * Unexpected OACK. TFTP transfer already in progress. + * Drop the pkt. + */ + if (d->xid != 1) { + return (-1); + } + /* - * Remember which port this OACK came from, - * because we need to send the ACK back to it. + * Remember which port this OACK came from, because we need + * to send the ACK or errors back to it. */ uh = (struct udphdr *) pkt - 1; d->destport = uh->uh_sport; + + /* Parse options ACK-ed by the server. */ + tftp_oack_len = len - sizeof(t->th_opcode); + if (tftp_parse_oack(h, t->th_u.tu_stuff, tftp_oack_len) != 0) { + tftp_senderr(h, EOPTNEG, "Malformed OACK"); + errno = EIO; + return (-1); + } return (0); } default: @@ -201,7 +265,7 @@ recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft, } /* send request, expect first block (or error) */ -static int +static int tftp_makereq(struct tftp_handle *h) { struct { @@ -250,26 +314,28 @@ tftp_makereq(struct tftp_handle *h) h->iodesc->destport = htons(IPPORT_TFTP); h->iodesc->xid = 1; /* expected block */ + h->currblock = 0; + h->islastblock = 0; + h->validsize = 0; + res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t, &recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype); - if (rtype == OACK) { - wbuf.t.th_opcode = htons((u_short)ACK); - wtail = (char *) &wbuf.t.th_block; - wbuf.t.th_block = htons(0); - wtail += 2; - rtype = 0; - res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t, - &recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype); - } + if (rtype == OACK) + return (tftp_getnextblock(h)); + + /* Server ignored our blksize request, revert to TFTP default. */ + h->tftp_blksize = SEGSIZE; switch (rtype) { case DATA: { h->currblock = 1; h->validsize = res; h->islastblock = 0; - if (res < h->tftp_blksize) + if (res < h->tftp_blksize) { h->islastblock = 1; /* very short file */ + tftp_sendack(h); + } return (0); } case ERROR: @@ -320,7 +386,7 @@ tftp_getnextblock(struct tftp_handle *h) return (0); } -static int +static int tftp_open(const char *path, struct open_file *f) { struct tftp_handle *tftpfile; @@ -365,7 +431,7 @@ tftp_open(const char *path, struct open_file *f) return (0); } -static int +static int tftp_read(struct open_file *f, void *addr, size_t size, size_t *resid /* out */) { @@ -381,9 +447,11 @@ tftp_read(struct open_file *f, void *addr, size_t size, needblock = tftpfile->off / tftpfile->tftp_blksize + 1; - if (tftpfile->currblock > needblock) /* seek backwards */ + if (tftpfile->currblock > needblock) { /* seek backwards */ + tftp_senderr(tftpfile, 0, "No error: read aborted"); tftp_makereq(tftpfile); /* no error check, it worked * for open */ + } while (tftpfile->currblock < needblock) { int res; @@ -452,7 +520,7 @@ tftp_close(struct open_file *f) return (0); } -static int +static int tftp_write(struct open_file *f __unused, void *start __unused, size_t size __unused, size_t *resid __unused /* out */) { @@ -473,7 +541,7 @@ tftp_stat(struct open_file *f, struct stat *sb) return (0); } -static off_t +static off_t tftp_seek(struct open_file *f, off_t offset, int where) { struct tftp_handle *tftpfile; @@ -494,7 +562,7 @@ tftp_seek(struct open_file *f, off_t offset, int where) } static ssize_t -sendrecv_tftp(struct tftp_handle *h, +sendrecv_tftp(struct tftp_handle *h, ssize_t (*sproc)(struct iodesc *, void *, size_t), void *sbuf, size_t ssize, ssize_t (*rproc)(struct tftp_handle *, void *, ssize_t, time_t, unsigned short *), @@ -562,9 +630,9 @@ tftp_set_blksize(struct tftp_handle *h, const char *str) /* * Only accept blksize value if it is numeric. - * RFC2348 specifies that acceptable valuesare 8-65464 - * 8-65464 . Let's choose a limit less than MAXRSPACE - */ + * RFC2348 specifies that acceptable values are 8-65464. + * Let's choose a limit less than MAXRSPACE. + */ if (*endptr == '\0' && new_blksize >= 8 && new_blksize <= TFTP_MAX_BLKSIZE) { h->tftp_blksize = new_blksize; @@ -597,13 +665,12 @@ tftp_set_blksize(struct tftp_handle *h, const char *str) * optN, valueN * The final option/value acknowledgment pair. */ -static void +static int tftp_parse_oack(struct tftp_handle *h, char *buf, size_t len) { /* * We parse the OACK strings into an array * of name-value pairs. - * */ char *tftp_options[128] = { 0 }; char *val = buf; @@ -612,18 +679,22 @@ tftp_parse_oack(struct tftp_handle *h, char *buf, size_t len) int blksize_is_set = 0; int tsize = 0; - - while ( option_idx < 128 && i < len ) { - if (buf[i] == '\0') { - if (&buf[i] > val) { - tftp_options[option_idx] = val; - val = &buf[i] + 1; - ++option_idx; - } - } - ++i; + unsigned int orig_blksize; + + while (option_idx < 128 && i < len) { + if (buf[i] == '\0') { + if (&buf[i] > val) { + tftp_options[option_idx] = val; + val = &buf[i] + 1; + ++option_idx; + } + } + ++i; } + /* Save the block size we requested for sanity check later. */ + orig_blksize = h->tftp_blksize; + /* * Parse individual TFTP options. * * "blksize" is specified in RFC2348. @@ -631,27 +702,37 @@ tftp_parse_oack(struct tftp_handle *h, char *buf, size_t len) */ for (i = 0; i < option_idx; i += 2) { if (strcasecmp(tftp_options[i], "blksize") == 0) { - if (i + 1 < option_idx) { + if (i + 1 < option_idx) blksize_is_set = tftp_set_blksize(h, tftp_options[i + 1]); - } } else if (strcasecmp(tftp_options[i], "tsize") == 0) { - if (i + 1 < option_idx) { + if (i + 1 < option_idx) tsize = strtol(tftp_options[i + 1], (char **)NULL, 10); - } + } else { + /* Do not allow any options we did not expect to be ACKed. */ + printf("unexpected tftp option '%s'\n", tftp_options[i]); + return (-1); } } if (!blksize_is_set) { /* * If TFTP blksize was not set, try defaulting - * to the legacy TFTP blksize of 512 + * to the legacy TFTP blksize of SEGSIZE(512) */ - h->tftp_blksize = 512; + h->tftp_blksize = SEGSIZE; + } else if (h->tftp_blksize > orig_blksize) { + /* + * Server should not be proposing block sizes that + * exceed what we said we can handle. + */ + printf("unexpected blksize %u\n", h->tftp_blksize); + return (-1); } #ifdef TFTP_DEBUG printf("tftp_blksize: %u\n", h->tftp_blksize); printf("tftp_tsize: %lu\n", h->tftp_tsize); #endif + return 0; } -- cgit v1.1 From 4f452fe5208cc332cd402007674b7f2ed324a9ac Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 04:16:06 +0000 Subject: - Add additional information to the PnP info of USB HUBs children which is now required by bus_autoconf. - Allow interface class matching even if device class is vendor specific. - Update bus_autoconf tool to not generate system and subsystem match lines for the nomatch event. PR: misc/157903 MFC after: 14 days --- sys/dev/usb/usb_hub.c | 6 +++++- sys/dev/usb/usb_lookup.c | 7 ------- tools/tools/bus_autoconf/bus_autoconf.c | 9 +-------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 351b134..12898ec 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -1334,15 +1334,19 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, "devclass=0x%02x devsubclass=0x%02x " "sernum=\"%s\" " "release=0x%04x " - "intclass=0x%02x intsubclass=0x%02x" "%s%s", + "mode=%s " + "intclass=0x%02x intsubclass=0x%02x " + "intprotocol=0x%02x " "%s%s", UGETW(res.udev->ddesc.idVendor), UGETW(res.udev->ddesc.idProduct), res.udev->ddesc.bDeviceClass, res.udev->ddesc.bDeviceSubClass, usb_get_serial(res.udev), UGETW(res.udev->ddesc.bcdDevice), + (res.udev->flags.usb_mode == USB_MODE_HOST) ? "host" : "device", iface->idesc->bInterfaceClass, iface->idesc->bInterfaceSubClass, + iface->idesc->bInterfaceProtocol, iface->pnpinfo ? " " : "", iface->pnpinfo ? iface->pnpinfo : ""); } else { diff --git a/sys/dev/usb/usb_lookup.c b/sys/dev/usb/usb_lookup.c index ced925e..3b2d16d 100644 --- a/sys/dev/usb/usb_lookup.c +++ b/sys/dev/usb/usb_lookup.c @@ -105,13 +105,6 @@ usbd_lookup_id_by_info(const struct usb_device_id *id, usb_size_t sizeof_id, (id->bDeviceProtocol != info->bDeviceProtocol)) { continue; } - if ((info->bDeviceClass == 0xFF) && - (!(id->match_flag_vendor)) && - ((id->match_flag_int_class) || - (id->match_flag_int_subclass) || - (id->match_flag_int_protocol))) { - continue; - } if ((id->match_flag_int_class) && (id->bInterfaceClass != info->bInterfaceClass)) { continue; diff --git a/tools/tools/bus_autoconf/bus_autoconf.c b/tools/tools/bus_autoconf/bus_autoconf.c index 68688af..0f7dbd5 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.c +++ b/tools/tools/bus_autoconf/bus_autoconf.c @@ -148,15 +148,8 @@ usb_dump(struct usb_device_id *id, uint32_t nid) usb_dump_sub(id, &info); - if (info.is_iface) { + if (info.is_any) { printf("nomatch 10 {\n" - " match \"system\" \"USB\";\n" - " match \"subsystem\" \"INTERFACE\";\n" - " match \"mode\" \"%s\";\n", mode); - } else if (info.is_any) { - printf("nomatch 10 {\n" - " match \"system\" \"USB\";\n" - " match \"subsystem\" \"DEVICE\";\n" " match \"mode\" \"%s\";\n", mode); } else { return (n); -- cgit v1.1 From cd28987a20ba09a274b684f82a701bd606278fc7 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 04:35:58 +0000 Subject: - Make sure we don't match the wrong device by adding a match for the bus the device belongs to. PR: misc/157903 MFC after: 14 days --- tools/tools/bus_autoconf/bus_autoconf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/tools/bus_autoconf/bus_autoconf.c b/tools/tools/bus_autoconf/bus_autoconf.c index 0f7dbd5..38fbd29 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.c +++ b/tools/tools/bus_autoconf/bus_autoconf.c @@ -150,6 +150,7 @@ usb_dump(struct usb_device_id *id, uint32_t nid) if (info.is_any) { printf("nomatch 10 {\n" + " match \"bus\" \"uhub[0-9]+\";\n" " match \"mode\" \"%s\";\n", mode); } else { return (n); -- cgit v1.1 From e3493c7d5460da801bcaa83327bcc05148764074 Mon Sep 17 00:00:00 2001 From: rodrigc Date: Fri, 24 Jun 2011 05:41:38 +0000 Subject: Acknowledge Edwin Groothuis for the major rewrite he did of the tftpd and tftp code to support TFTP blocksize. --- libexec/tftpd/tftpd.8 | 6 ++++++ usr.bin/tftp/tftp.1 | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8 index c8474d2..96bd24c 100644 --- a/libexec/tftpd/tftpd.8 +++ b/libexec/tftpd/tftpd.8 @@ -293,6 +293,12 @@ was introduced in support for the TFTP Blocksize Option (RFC2348) and the blksize2 option was introduced in .Fx 7.4 . +.Pp +Edwin Groothuis performed a major rewrite of the +.Nm +and +.Xr tftp 1 +code to support RFC2348. .Sh NOTES Files larger than 33488896 octets (65535 blocks) cannot be transferred without client and server supporting the TFTP blocksize option (RFC2348), diff --git a/usr.bin/tftp/tftp.1 b/usr.bin/tftp/tftp.1 index 8c58352..02709c0 100644 --- a/usr.bin/tftp/tftp.1 +++ b/usr.bin/tftp/tftp.1 @@ -218,7 +218,7 @@ Toggle packet tracing. Toggle verbose mode. .El .Sh SEE ALSO -.Xr tftp 1 +.Xr tftpd 8 .Pp The following RFC's are supported: .Rs @@ -256,6 +256,12 @@ The .Nm command appeared in .Bx 4.3 . +.Pp +Edwin Groothuis performed a major rewrite of the +.Xr tftpd 8 +and +.Nm +code to support RFC2348. .Sh NOTES Because there is no user-login or validation within the -- cgit v1.1 From 80dd636e8f80c9e1d3830ef8dfbef4f0191dacc3 Mon Sep 17 00:00:00 2001 From: kevlo Date: Fri, 24 Jun 2011 07:05:20 +0000 Subject: Remove duplicated header files --- usr.sbin/ancontrol/ancontrol.c | 1 - usr.sbin/ifmcstat/ifmcstat.c | 1 - usr.sbin/nfsd/nfsd.c | 1 - usr.sbin/pmcstat/pmcpl_calltree.c | 1 - usr.sbin/ppp/nat_cmd.c | 1 - usr.sbin/rpc.yppasswdd/yppasswdd_main.c | 1 - usr.sbin/rpc.ypupdated/update.c | 1 - usr.sbin/rpc.ypupdated/ypupdated_main.c | 1 - usr.sbin/rpc.ypupdated/ypupdated_server.c | 1 - usr.sbin/sysinstall/modules.c | 1 - usr.sbin/wpa/ndis_events/ndis_events.c | 2 -- usr.sbin/wpa/wpa_supplicant/Packet32.c | 1 - 12 files changed, 13 deletions(-) diff --git a/usr.sbin/ancontrol/ancontrol.c b/usr.sbin/ancontrol/ancontrol.c index 008970d..4a11453 100644 --- a/usr.sbin/ancontrol/ancontrol.c +++ b/usr.sbin/ancontrol/ancontrol.c @@ -40,7 +40,6 @@ static const char copyright[] = "@(#) Copyright (c) 1997, 1998, 1999\ __FBSDID("$FreeBSD$"); #include -#include #include #include diff --git a/usr.sbin/ifmcstat/ifmcstat.c b/usr.sbin/ifmcstat/ifmcstat.c index e45e36d..5ee4328 100644 --- a/usr.sbin/ifmcstat/ifmcstat.c +++ b/usr.sbin/ifmcstat/ifmcstat.c @@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c index 656cb14..c5cec5e 100644 --- a/usr.sbin/nfsd/nfsd.c +++ b/usr.sbin/nfsd/nfsd.c @@ -71,7 +71,6 @@ static const char rcsid[] = #include #include #include -#include /* Global defs */ #ifdef DEBUG diff --git a/usr.sbin/pmcstat/pmcpl_calltree.c b/usr.sbin/pmcstat/pmcpl_calltree.c index c647a32..af3317a 100644 --- a/usr.sbin/pmcstat/pmcpl_calltree.c +++ b/usr.sbin/pmcstat/pmcpl_calltree.c @@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/usr.sbin/ppp/nat_cmd.c b/usr.sbin/ppp/nat_cmd.c index 48f894a..accb149 100644 --- a/usr.sbin/ppp/nat_cmd.c +++ b/usr.sbin/ppp/nat_cmd.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c index 8c89691..38719c4 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include #include #include /* getenv, exit */ -#include #include /* strcmp */ #include #include diff --git a/usr.sbin/rpc.ypupdated/update.c b/usr.sbin/rpc.ypupdated/update.c index 72a7128..956b057 100644 --- a/usr.sbin/rpc.ypupdated/update.c +++ b/usr.sbin/rpc.ypupdated/update.c @@ -57,7 +57,6 @@ static const char rcsid[] = #include #include #include -#include #include "ypupdated_extern.h" #ifdef YP diff --git a/usr.sbin/rpc.ypupdated/ypupdated_main.c b/usr.sbin/rpc.ypupdated/ypupdated_main.c index c13af7d..92d8374 100644 --- a/usr.sbin/rpc.ypupdated/ypupdated_main.c +++ b/usr.sbin/rpc.ypupdated/ypupdated_main.c @@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include "ypupdated_extern.h" #include "yp_extern.h" diff --git a/usr.sbin/rpc.ypupdated/ypupdated_server.c b/usr.sbin/rpc.ypupdated/ypupdated_server.c index c9a50dd..c4e163a 100644 --- a/usr.sbin/rpc.ypupdated/ypupdated_server.c +++ b/usr.sbin/rpc.ypupdated/ypupdated_server.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include "ypupdate_prot.h" #include "ypupdated_extern.h" diff --git a/usr.sbin/sysinstall/modules.c b/usr.sbin/sysinstall/modules.c index e9bdb0f..9c9875f 100644 --- a/usr.sbin/sysinstall/modules.c +++ b/usr.sbin/sysinstall/modules.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/usr.sbin/wpa/ndis_events/ndis_events.c b/usr.sbin/wpa/ndis_events/ndis_events.c index e3cd9b5..9c6e9de 100644 --- a/usr.sbin/wpa/ndis_events/ndis_events.c +++ b/usr.sbin/wpa/ndis_events/ndis_events.c @@ -42,11 +42,9 @@ __FBSDID("$FreeBSD$"); */ #include -#include #include #include #include -#include #include #include #include diff --git a/usr.sbin/wpa/wpa_supplicant/Packet32.c b/usr.sbin/wpa/wpa_supplicant/Packet32.c index 07da359..876417e 100644 --- a/usr.sbin/wpa/wpa_supplicant/Packet32.c +++ b/usr.sbin/wpa/wpa_supplicant/Packet32.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include -- cgit v1.1 From 9304e224e74af981127c0d8c72015e36a2c06743 Mon Sep 17 00:00:00 2001 From: kevlo Date: Fri, 24 Jun 2011 07:18:44 +0000 Subject: Remove duplicated header files --- usr.bin/ktrace/ktrace.c | 1 - usr.bin/ncplogin/ncplogin.c | 2 -- usr.bin/systat/netstat.c | 1 - usr.bin/tftp/main.c | 1 - usr.bin/vmstat/vmstat.c | 1 - 5 files changed, 6 deletions(-) diff --git a/usr.bin/ktrace/ktrace.c b/usr.bin/ktrace/ktrace.c index fa2fa1a..4490849 100644 --- a/usr.bin/ktrace/ktrace.c +++ b/usr.bin/ktrace/ktrace.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/usr.bin/ncplogin/ncplogin.c b/usr.bin/ncplogin/ncplogin.c index 05b95c1..edb903e 100644 --- a/usr.bin/ncplogin/ncplogin.c +++ b/usr.bin/ncplogin/ncplogin.c @@ -42,8 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include #include diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c index 2f8ca0a..b1c6dc9 100644 --- a/usr.bin/systat/netstat.c +++ b/usr.bin/systat/netstat.c @@ -63,7 +63,6 @@ static const char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93"; #define TCPSTATES #include #include -#include #include #include #include diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c index 2bdcf5f..da0e5df 100644 --- a/usr.bin/tftp/main.c +++ b/usr.bin/tftp/main.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include diff --git a/usr.bin/vmstat/vmstat.c b/usr.bin/vmstat/vmstat.c index cda77ad..d31fdb5 100644 --- a/usr.bin/vmstat/vmstat.c +++ b/usr.bin/vmstat/vmstat.c @@ -43,7 +43,6 @@ static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93"; __FBSDID("$FreeBSD$"); #include -#include #include #include #include -- cgit v1.1 From c1214139ee347d79c2659ca792a5dd27cbd0c9b1 Mon Sep 17 00:00:00 2001 From: kevlo Date: Fri, 24 Jun 2011 07:29:04 +0000 Subject: Remove duplicated header files --- bin/rcp/rcp.c | 1 - bin/sh/mkinit.c | 1 - sbin/savecore/savecore.c | 1 - 3 files changed, 3 deletions(-) diff --git a/bin/rcp/rcp.c b/bin/rcp/rcp.c index 2c27b63..4577b20 100644 --- a/bin/rcp/rcp.c +++ b/bin/rcp/rcp.c @@ -71,7 +71,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include "extern.h" diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c index 866b238..1d1d93e 100644 --- a/bin/sh/mkinit.c +++ b/bin/sh/mkinit.c @@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$"); */ -#include #include #include #include diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index d54fcf5..ea715f3 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -66,7 +66,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include -- cgit v1.1 From 7549fd80dceb76179c8bba85df341a74e670d373 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 11:14:09 +0000 Subject: - Add two new API's to libusb20 which can be used to retrive information about the parent USB device: - libusb20_dev_get_parent_address - libusb20_dev_get_parent_port - Rename libusb20_compat01.c into libusb01.c MFC after: 3 days --- lib/libusb/Makefile | 4 +- lib/libusb/libusb01.c | 945 +++++++++++++++++++++++++++++++++++++++++ lib/libusb/libusb20.3 | 23 + lib/libusb/libusb20.c | 12 + lib/libusb/libusb20.h | 2 + lib/libusb/libusb20_compat01.c | 945 ----------------------------------------- lib/libusb/libusb20_int.h | 2 + lib/libusb/libusb20_ugen20.c | 5 + 8 files changed, 992 insertions(+), 946 deletions(-) create mode 100644 lib/libusb/libusb01.c delete mode 100644 lib/libusb/libusb20_compat01.c diff --git a/lib/libusb/Makefile b/lib/libusb/Makefile index debbfa2..f438cff 100644 --- a/lib/libusb/Makefile +++ b/lib/libusb/Makefile @@ -22,7 +22,7 @@ MLINKS+= libusb.3 usb.3 # libusb 0.1 compat INCS+= usb.h -SRCS+= libusb20_compat01.c +SRCS+= libusb01.c # libusb 1.0 compat INCS+= libusb.h @@ -184,6 +184,8 @@ MLINKS += libusb20.3 libusb20_dev_get_device_desc.3 MLINKS += libusb20.3 libusb20_dev_alloc_config.3 MLINKS += libusb20.3 libusb20_dev_alloc.3 MLINKS += libusb20.3 libusb20_dev_get_address.3 +MLINKS += libusb20.3 libusb20_dev_get_parent_address.3 +MLINKS += libusb20.3 libusb20_dev_get_parent_port.3 MLINKS += libusb20.3 libusb20_dev_get_bus_number.3 MLINKS += libusb20.3 libusb20_dev_get_mode.3 MLINKS += libusb20.3 libusb20_dev_get_speed.3 diff --git a/lib/libusb/libusb01.c b/lib/libusb/libusb01.c new file mode 100644 index 0000000..4124ef6 --- /dev/null +++ b/lib/libusb/libusb01.c @@ -0,0 +1,945 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2008 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +/* + * This file contains the emulation layer for LibUSB v0.1 from sourceforge. + */ + +#include + +#include +#include +#include + +#include "libusb20.h" +#include "libusb20_desc.h" +#include "libusb20_int.h" +#include "usb.h" + +/* + * The two following macros were taken from the original LibUSB v0.1 + * for sake of compatibility: + */ +#define LIST_ADD(begin, ent) \ + do { \ + if (begin) { \ + ent->next = begin; \ + ent->next->prev = ent; \ + } else { \ + ent->next = NULL; \ + } \ + ent->prev = NULL; \ + begin = ent; \ + } while(0) + +#define LIST_DEL(begin, ent) \ + do { \ + if (ent->prev) { \ + ent->prev->next = ent->next; \ + } else { \ + begin = ent->next; \ + } \ + if (ent->next) { \ + ent->next->prev = ent->prev; \ + } \ + ent->prev = NULL; \ + ent->next = NULL; \ + } while (0) + +struct usb_bus *usb_busses = NULL; + +static struct usb_bus usb_global_bus = { + .dirname = {"/dev/usb"}, + .root_dev = NULL, + .devices = NULL, +}; + +static struct libusb20_backend *usb_backend = NULL; + +struct usb_parse_state { + + struct { + struct libusb20_endpoint *currep; + struct libusb20_interface *currifc; + struct libusb20_config *currcfg; + struct libusb20_me_struct *currextra; + } a; + + struct { + struct usb_config_descriptor *currcfg; + struct usb_interface_descriptor *currifc; + struct usb_endpoint_descriptor *currep; + struct usb_interface *currifcw; + uint8_t *currextra; + } b; + + uint8_t preparse; +}; + +static struct libusb20_transfer * +usb_get_transfer_by_ep_no(usb_dev_handle * dev, uint8_t ep_no) +{ + struct libusb20_device *pdev = (void *)dev; + struct libusb20_transfer *xfer; + int err; + uint32_t bufsize; + uint8_t x; + uint8_t speed; + + x = (ep_no & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 2; + + if (ep_no & LIBUSB20_ENDPOINT_DIR_MASK) { + /* this is an IN endpoint */ + x |= 1; + } + speed = libusb20_dev_get_speed(pdev); + + /* select a sensible buffer size */ + if (speed == LIBUSB20_SPEED_LOW) { + bufsize = 256; + } else if (speed == LIBUSB20_SPEED_FULL) { + bufsize = 4096; + } else { + bufsize = 16384; + } + + xfer = libusb20_tr_get_pointer(pdev, x); + + if (xfer == NULL) + return (xfer); + + err = libusb20_tr_open(xfer, bufsize, 1, ep_no); + if (err == LIBUSB20_ERROR_BUSY) { + /* already opened */ + return (xfer); + } else if (err) { + return (NULL); + } + /* success */ + return (xfer); +} + +usb_dev_handle * +usb_open(struct usb_device *dev) +{ + int err; + + err = libusb20_dev_open(dev->dev, 16 * 2); + if (err == LIBUSB20_ERROR_BUSY) { + /* + * Workaround buggy USB applications which open the USB + * device multiple times: + */ + return (dev->dev); + } + if (err) + return (NULL); + + /* + * Dequeue USB device from backend queue so that it does not get + * freed when the backend is re-scanned: + */ + libusb20_be_dequeue_device(usb_backend, dev->dev); + + return (dev->dev); +} + +int +usb_close(usb_dev_handle * udev) +{ + struct usb_device *dev; + int err; + + err = libusb20_dev_close((void *)udev); + + if (err) + return (-1); + + if (usb_backend != NULL) { + /* + * Enqueue USB device to backend queue so that it gets freed + * when the backend is re-scanned: + */ + libusb20_be_enqueue_device(usb_backend, (void *)udev); + } else { + /* + * The backend is gone. Free device data so that we + * don't start leaking memory! + */ + dev = usb_device(udev); + libusb20_dev_free((void *)udev); + LIST_DEL(usb_global_bus.devices, dev); + free(dev); + } + return (0); +} + +int +usb_get_string(usb_dev_handle * dev, int strindex, + int langid, char *buf, size_t buflen) +{ + int err; + + err = libusb20_dev_req_string_sync((void *)dev, + strindex, langid, buf, buflen); + + if (err) + return (-1); + + return (0); +} + +int +usb_get_string_simple(usb_dev_handle * dev, int strindex, + char *buf, size_t buflen) +{ + int err; + + err = libusb20_dev_req_string_simple_sync((void *)dev, + strindex, buf, buflen); + + if (err) + return (-1); + + return (strlen(buf)); +} + +int +usb_get_descriptor_by_endpoint(usb_dev_handle * udev, int ep, uint8_t type, + uint8_t ep_index, void *buf, int size) +{ + memset(buf, 0, size); + + return (usb_control_msg(udev, ep | USB_ENDPOINT_IN, + USB_REQ_GET_DESCRIPTOR, (type << 8) + ep_index, 0, + buf, size, 1000)); +} + +int +usb_get_descriptor(usb_dev_handle * udev, uint8_t type, uint8_t desc_index, + void *buf, int size) +{ + memset(buf, 0, size); + + return (usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, + (type << 8) + desc_index, 0, buf, size, 1000)); +} + +int +usb_parse_descriptor(uint8_t *source, char *description, void *dest) +{ + uint8_t *sp = source; + uint8_t *dp = dest; + uint16_t w; + uint32_t d; + char *cp; + + for (cp = description; *cp; cp++) { + switch (*cp) { + case 'b': /* 8-bit byte */ + *dp++ = *sp++; + break; + /* + * 16-bit word, convert from little endian to CPU + */ + case 'w': + w = (sp[1] << 8) | sp[0]; + sp += 2; + /* Align to word boundary */ + dp += ((dp - (uint8_t *)0) & 1); + *((uint16_t *)dp) = w; + dp += 2; + break; + /* + * 32-bit dword, convert from little endian to CPU + */ + case 'd': + d = (sp[3] << 24) | (sp[2] << 16) | + (sp[1] << 8) | sp[0]; + sp += 4; + /* Align to word boundary */ + dp += ((dp - (uint8_t *)0) & 1); + /* Align to double word boundary */ + dp += ((dp - (uint8_t *)0) & 2); + *((uint32_t *)dp) = d; + dp += 4; + break; + } + } + return (sp - source); +} + +static void +usb_parse_extra(struct usb_parse_state *ps, uint8_t **pptr, int *plen) +{ + void *ptr; + uint16_t len; + + ptr = ps->a.currextra->ptr; + len = ps->a.currextra->len; + + if (ps->preparse == 0) { + memcpy(ps->b.currextra, ptr, len); + *pptr = ps->b.currextra; + *plen = len; + } + ps->b.currextra += len; + return; +} + +static void +usb_parse_endpoint(struct usb_parse_state *ps) +{ + struct usb_endpoint_descriptor *bep; + struct libusb20_endpoint *aep; + + aep = ps->a.currep; + bep = ps->b.currep++; + + if (ps->preparse == 0) { + /* copy descriptor fields */ + bep->bLength = aep->desc.bLength; + bep->bDescriptorType = aep->desc.bDescriptorType; + bep->bEndpointAddress = aep->desc.bEndpointAddress; + bep->bmAttributes = aep->desc.bmAttributes; + bep->wMaxPacketSize = aep->desc.wMaxPacketSize; + bep->bInterval = aep->desc.bInterval; + bep->bRefresh = aep->desc.bRefresh; + bep->bSynchAddress = aep->desc.bSynchAddress; + } + ps->a.currextra = &aep->extra; + usb_parse_extra(ps, &bep->extra, &bep->extralen); + return; +} + +static void +usb_parse_iface_sub(struct usb_parse_state *ps) +{ + struct libusb20_interface *aifc; + struct usb_interface_descriptor *bifc; + uint8_t x; + + aifc = ps->a.currifc; + bifc = ps->b.currifc++; + + if (ps->preparse == 0) { + /* copy descriptor fields */ + bifc->bLength = aifc->desc.bLength; + bifc->bDescriptorType = aifc->desc.bDescriptorType; + bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber; + bifc->bAlternateSetting = aifc->desc.bAlternateSetting; + bifc->bNumEndpoints = aifc->num_endpoints; + bifc->bInterfaceClass = aifc->desc.bInterfaceClass; + bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass; + bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol; + bifc->iInterface = aifc->desc.iInterface; + bifc->endpoint = ps->b.currep; + } + for (x = 0; x != aifc->num_endpoints; x++) { + ps->a.currep = aifc->endpoints + x; + usb_parse_endpoint(ps); + } + + ps->a.currextra = &aifc->extra; + usb_parse_extra(ps, &bifc->extra, &bifc->extralen); + return; +} + +static void +usb_parse_iface(struct usb_parse_state *ps) +{ + struct libusb20_interface *aifc; + struct usb_interface *bifc; + uint8_t x; + + aifc = ps->a.currifc; + bifc = ps->b.currifcw++; + + if (ps->preparse == 0) { + /* initialise interface wrapper */ + bifc->altsetting = ps->b.currifc; + bifc->num_altsetting = aifc->num_altsetting + 1; + } + usb_parse_iface_sub(ps); + + for (x = 0; x != aifc->num_altsetting; x++) { + ps->a.currifc = aifc->altsetting + x; + usb_parse_iface_sub(ps); + } + return; +} + +static void +usb_parse_config(struct usb_parse_state *ps) +{ + struct libusb20_config *acfg; + struct usb_config_descriptor *bcfg; + uint8_t x; + + acfg = ps->a.currcfg; + bcfg = ps->b.currcfg; + + if (ps->preparse == 0) { + /* initialise config wrapper */ + bcfg->bLength = acfg->desc.bLength; + bcfg->bDescriptorType = acfg->desc.bDescriptorType; + bcfg->wTotalLength = acfg->desc.wTotalLength; + bcfg->bNumInterfaces = acfg->num_interface; + bcfg->bConfigurationValue = acfg->desc.bConfigurationValue; + bcfg->iConfiguration = acfg->desc.iConfiguration; + bcfg->bmAttributes = acfg->desc.bmAttributes; + bcfg->MaxPower = acfg->desc.bMaxPower; + bcfg->interface = ps->b.currifcw; + } + for (x = 0; x != acfg->num_interface; x++) { + ps->a.currifc = acfg->interface + x; + usb_parse_iface(ps); + } + + ps->a.currextra = &acfg->extra; + usb_parse_extra(ps, &bcfg->extra, &bcfg->extralen); + return; +} + +int +usb_parse_configuration(struct usb_config_descriptor *config, + uint8_t *buffer) +{ + struct usb_parse_state ps; + uint8_t *ptr; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; + + if ((buffer == NULL) || (config == NULL)) { + return (-1); + } + memset(&ps, 0, sizeof(ps)); + + ps.a.currcfg = libusb20_parse_config_desc(buffer); + ps.b.currcfg = config; + if (ps.a.currcfg == NULL) { + /* could not parse config or out of memory */ + return (-1); + } + /* do the pre-parse */ + ps.preparse = 1; + usb_parse_config(&ps); + + a = ((uint8_t *)(ps.b.currifcw) - ((uint8_t *)0)); + b = ((uint8_t *)(ps.b.currifc) - ((uint8_t *)0)); + c = ((uint8_t *)(ps.b.currep) - ((uint8_t *)0)); + d = ((uint8_t *)(ps.b.currextra) - ((uint8_t *)0)); + + /* allocate memory for our configuration */ + ptr = malloc(a + b + c + d); + if (ptr == NULL) { + /* free config structure */ + free(ps.a.currcfg); + return (-1); + } + + /* "currifcw" must be first, hence this pointer is freed */ + ps.b.currifcw = (void *)(ptr); + ps.b.currifc = (void *)(ptr + a); + ps.b.currep = (void *)(ptr + a + b); + ps.b.currextra = (void *)(ptr + a + b + c); + + /* generate a libusb v0.1 compatible structure */ + ps.preparse = 0; + usb_parse_config(&ps); + + /* free config structure */ + free(ps.a.currcfg); + + return (0); /* success */ +} + +void +usb_destroy_configuration(struct usb_device *dev) +{ + uint8_t c; + + if (dev->config == NULL) { + return; + } + for (c = 0; c != dev->descriptor.bNumConfigurations; c++) { + struct usb_config_descriptor *cf = &dev->config[c]; + + if (cf->interface != NULL) { + free(cf->interface); + cf->interface = NULL; + } + } + + free(dev->config); + dev->config = NULL; + return; +} + +void +usb_fetch_and_parse_descriptors(usb_dev_handle * udev) +{ + struct usb_device *dev; + struct libusb20_device *pdev; + uint8_t *ptr; + int error; + uint32_t size; + uint16_t len; + uint8_t x; + + if (udev == NULL) { + /* be NULL safe */ + return; + } + dev = usb_device(udev); + pdev = (void *)udev; + + if (dev->descriptor.bNumConfigurations == 0) { + /* invalid device */ + return; + } + size = dev->descriptor.bNumConfigurations * + sizeof(struct usb_config_descriptor); + + dev->config = malloc(size); + if (dev->config == NULL) { + /* out of memory */ + return; + } + memset(dev->config, 0, size); + + for (x = 0; x != dev->descriptor.bNumConfigurations; x++) { + + error = (pdev->methods->get_config_desc_full) ( + pdev, &ptr, &len, x); + + if (error) { + usb_destroy_configuration(dev); + return; + } + usb_parse_configuration(dev->config + x, ptr); + + /* free config buffer */ + free(ptr); + } + return; +} + +static int +usb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size, + int timeout, int is_intr) +{ + struct libusb20_transfer *xfer; + uint32_t temp; + uint32_t maxsize; + uint32_t actlen; + char *oldbytes; + + xfer = usb_get_transfer_by_ep_no(dev, ep); + if (xfer == NULL) + return (-1); + + if (libusb20_tr_pending(xfer)) { + /* there is already a transfer ongoing */ + return (-1); + } + maxsize = libusb20_tr_get_max_total_length(xfer); + oldbytes = bytes; + + /* + * We allow transferring zero bytes which is the same + * equivalent to a zero length USB packet. + */ + do { + + temp = size; + if (temp > maxsize) { + /* find maximum possible length */ + temp = maxsize; + } + if (is_intr) + libusb20_tr_setup_intr(xfer, bytes, temp, timeout); + else + libusb20_tr_setup_bulk(xfer, bytes, temp, timeout); + + libusb20_tr_start(xfer); + + while (1) { + + if (libusb20_dev_process((void *)dev) != 0) { + /* device detached */ + return (-1); + } + if (libusb20_tr_pending(xfer) == 0) { + /* transfer complete */ + break; + } + /* wait for USB event from kernel */ + libusb20_dev_wait_process((void *)dev, -1); + } + + switch (libusb20_tr_get_status(xfer)) { + case 0: + /* success */ + break; + case LIBUSB20_TRANSFER_TIMED_OUT: + /* transfer timeout */ + return (-ETIMEDOUT); + default: + /* other transfer error */ + return (-ENXIO); + } + actlen = libusb20_tr_get_actual_length(xfer); + + bytes += actlen; + size -= actlen; + + if (actlen != temp) { + /* short transfer */ + break; + } + } while (size > 0); + + return (bytes - oldbytes); +} + +int +usb_bulk_write(usb_dev_handle * dev, int ep, char *bytes, + int size, int timeout) +{ + return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, + bytes, size, timeout, 0)); +} + +int +usb_bulk_read(usb_dev_handle * dev, int ep, char *bytes, + int size, int timeout) +{ + return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, + bytes, size, timeout, 0)); +} + +int +usb_interrupt_write(usb_dev_handle * dev, int ep, char *bytes, + int size, int timeout) +{ + return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, + bytes, size, timeout, 1)); +} + +int +usb_interrupt_read(usb_dev_handle * dev, int ep, char *bytes, + int size, int timeout) +{ + return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, + bytes, size, timeout, 1)); +} + +int +usb_control_msg(usb_dev_handle * dev, int requesttype, int request, + int value, int wIndex, char *bytes, int size, int timeout) +{ + struct LIBUSB20_CONTROL_SETUP_DECODED req; + int err; + uint16_t actlen; + + LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); + + req.bmRequestType = requesttype; + req.bRequest = request; + req.wValue = value; + req.wIndex = wIndex; + req.wLength = size; + + err = libusb20_dev_request_sync((void *)dev, &req, bytes, + &actlen, timeout, 0); + + if (err) + return (-1); + + return (actlen); +} + +int +usb_set_configuration(usb_dev_handle * udev, int bConfigurationValue) +{ + struct usb_device *dev; + int err; + uint8_t i; + + /* + * Need to translate from "bConfigurationValue" to + * configuration index: + */ + + if (bConfigurationValue == 0) { + /* unconfigure */ + i = 255; + } else { + /* lookup configuration index */ + dev = usb_device(udev); + + /* check if the configuration array is not there */ + if (dev->config == NULL) { + return (-1); + } + for (i = 0;; i++) { + if (i == dev->descriptor.bNumConfigurations) { + /* "bConfigurationValue" not found */ + return (-1); + } + if ((dev->config + i)->bConfigurationValue == + bConfigurationValue) { + break; + } + } + } + + err = libusb20_dev_set_config_index((void *)udev, i); + + if (err) + return (-1); + + return (0); +} + +int +usb_claim_interface(usb_dev_handle * dev, int interface) +{ + struct libusb20_device *pdev = (void *)dev; + + pdev->claimed_interface = interface; + + return (0); +} + +int +usb_release_interface(usb_dev_handle * dev, int interface) +{ + /* do nothing */ + return (0); +} + +int +usb_set_altinterface(usb_dev_handle * dev, int alternate) +{ + struct libusb20_device *pdev = (void *)dev; + int err; + uint8_t iface; + + iface = pdev->claimed_interface; + + err = libusb20_dev_set_alt_index((void *)dev, iface, alternate); + + if (err) + return (-1); + + return (0); +} + +int +usb_resetep(usb_dev_handle * dev, unsigned int ep) +{ + /* emulate an endpoint reset through clear-STALL */ + return (usb_clear_halt(dev, ep)); +} + +int +usb_clear_halt(usb_dev_handle * dev, unsigned int ep) +{ + struct libusb20_transfer *xfer; + + xfer = usb_get_transfer_by_ep_no(dev, ep); + if (xfer == NULL) + return (-1); + + libusb20_tr_clear_stall_sync(xfer); + + return (0); +} + +int +usb_reset(usb_dev_handle * dev) +{ + int err; + + err = libusb20_dev_reset((void *)dev); + + if (err) + return (-1); + + /* + * Be compatible with LibUSB from sourceforge and close the + * handle after reset! + */ + return (usb_close(dev)); +} + +int +usb_check_connected(usb_dev_handle * dev) +{ + int err; + + err = libusb20_dev_check_connected((void *)dev); + + if (err) + return (-1); + + return (0); +} + +const char * +usb_strerror(void) +{ + /* TODO */ + return ("Unknown error"); +} + +void +usb_init(void) +{ + /* nothing to do */ + return; +} + +void +usb_set_debug(int level) +{ + /* use kernel UGEN debugging if you need to see what is going on */ + return; +} + +int +usb_find_busses(void) +{ + usb_busses = &usb_global_bus; + return (1); +} + +int +usb_find_devices(void) +{ + struct libusb20_device *pdev; + struct usb_device *udev; + struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; + int devnum; + int err; + + /* cleanup after last device search */ + /* close all opened devices, if any */ + + while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { + udev = pdev->privLuData; + libusb20_be_dequeue_device(usb_backend, pdev); + libusb20_dev_free(pdev); + if (udev != NULL) { + LIST_DEL(usb_global_bus.devices, udev); + free(udev); + } + } + + /* free old USB backend, if any */ + + libusb20_be_free(usb_backend); + + /* do a new backend device search */ + usb_backend = libusb20_be_alloc_default(); + if (usb_backend == NULL) { + return (-1); + } + /* iterate all devices */ + + devnum = 1; + pdev = NULL; + while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) { + udev = malloc(sizeof(*udev)); + if (udev == NULL) + break; + + memset(udev, 0, sizeof(*udev)); + + udev->bus = &usb_global_bus; + + snprintf(udev->filename, sizeof(udev->filename), + "/dev/ugen%u.%u", + libusb20_dev_get_bus_number(pdev), + libusb20_dev_get_address(pdev)); + + ddesc = libusb20_dev_get_device_desc(pdev); + + udev->descriptor.bLength = sizeof(udev->descriptor); + udev->descriptor.bDescriptorType = ddesc->bDescriptorType; + udev->descriptor.bcdUSB = ddesc->bcdUSB; + udev->descriptor.bDeviceClass = ddesc->bDeviceClass; + udev->descriptor.bDeviceSubClass = ddesc->bDeviceSubClass; + udev->descriptor.bDeviceProtocol = ddesc->bDeviceProtocol; + udev->descriptor.bMaxPacketSize0 = ddesc->bMaxPacketSize0; + udev->descriptor.idVendor = ddesc->idVendor; + udev->descriptor.idProduct = ddesc->idProduct; + udev->descriptor.bcdDevice = ddesc->bcdDevice; + udev->descriptor.iManufacturer = ddesc->iManufacturer; + udev->descriptor.iProduct = ddesc->iProduct; + udev->descriptor.iSerialNumber = ddesc->iSerialNumber; + udev->descriptor.bNumConfigurations = + ddesc->bNumConfigurations; + if (udev->descriptor.bNumConfigurations > USB_MAXCONFIG) { + /* truncate number of configurations */ + udev->descriptor.bNumConfigurations = USB_MAXCONFIG; + } + udev->devnum = devnum++; + /* link together the two structures */ + udev->dev = pdev; + pdev->privLuData = udev; + + err = libusb20_dev_open(pdev, 0); + if (err == 0) { + /* XXX get all config descriptors by default */ + usb_fetch_and_parse_descriptors((void *)pdev); + libusb20_dev_close(pdev); + } + LIST_ADD(usb_global_bus.devices, udev); + } + + return (devnum - 1); /* success */ +} + +struct usb_device * +usb_device(usb_dev_handle * dev) +{ + struct libusb20_device *pdev; + + pdev = (void *)dev; + + return (pdev->privLuData); +} + +struct usb_bus * +usb_get_busses(void) +{ + return (usb_busses); +} diff --git a/lib/libusb/libusb20.3 b/lib/libusb/libusb20.3 index 93dfe18..042f885 100644 --- a/lib/libusb/libusb20.3 +++ b/lib/libusb/libusb20.3 @@ -159,6 +159,10 @@ USB access library (libusb -lusb) .Ft uint8_t .Fn libusb20_dev_get_address "struct libusb20_device *pdev" .Ft uint8_t +.Fn libusb20_dev_get_parent_address "struct libusb20_device *pdev" +.Ft uint8_t +.Fn libusb20_dev_get_parent_port "struct libusb20_device *pdev" +.Ft uint8_t .Fn libusb20_dev_get_bus_number "struct libusb20_device *pdev" .Ft uint8_t .Fn libusb20_dev_get_mode "struct libusb20_device *pdev" @@ -756,12 +760,31 @@ is an internal function to allocate a new USB device. .Fn libusb20_dev_get_address returns the internal and not necessarily the real hardware address of the given USB device. +Valid addresses start at one. +. +.Pp +. +.Fn libusb20_dev_get_parent_address +returns the internal and not necessarily the real hardware address of +the given parent USB HUB device. +This value is zero for the root HUB which usually has a device address +equal to one. +Valid addresses start at one. +. +.Pp +. +.Fn libusb20_dev_get_parent_port +returns the port number on the parent USB HUB device. +This value is zero for the root HUB which usually has a device address +equal to one. +Valid port numbers start at one. . .Pp . .Fn libusb20_dev_get_bus_number returns the internal bus number which the given USB device belongs to. +Valid bus numbers start at zero. . .Pp . diff --git a/lib/libusb/libusb20.c b/lib/libusb/libusb20.c index bcaa1e4..716f540 100644 --- a/lib/libusb/libusb20.c +++ b/lib/libusb/libusb20.c @@ -1057,6 +1057,18 @@ libusb20_dev_get_address(struct libusb20_device *pdev) } uint8_t +libusb20_dev_get_parent_address(struct libusb20_device *pdev) +{ + return (pdev->parent_address); +} + +uint8_t +libusb20_dev_get_parent_port(struct libusb20_device *pdev) +{ + return (pdev->parent_port); +} + +uint8_t libusb20_dev_get_bus_number(struct libusb20_device *pdev) { return (pdev->bus_number); diff --git a/lib/libusb/libusb20.h b/lib/libusb/libusb20.h index 958a379..22a2899 100644 --- a/lib/libusb/libusb20.h +++ b/lib/libusb/libusb20.h @@ -262,6 +262,8 @@ struct LIBUSB20_DEVICE_DESC_DECODED *libusb20_dev_get_device_desc(struct libusb2 struct libusb20_config *libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t config_index); struct libusb20_device *libusb20_dev_alloc(void); uint8_t libusb20_dev_get_address(struct libusb20_device *pdev); +uint8_t libusb20_dev_get_parent_address(struct libusb20_device *pdev); +uint8_t libusb20_dev_get_parent_port(struct libusb20_device *pdev); uint8_t libusb20_dev_get_bus_number(struct libusb20_device *pdev); uint8_t libusb20_dev_get_mode(struct libusb20_device *pdev); uint8_t libusb20_dev_get_speed(struct libusb20_device *pdev); diff --git a/lib/libusb/libusb20_compat01.c b/lib/libusb/libusb20_compat01.c deleted file mode 100644 index 4124ef6..0000000 --- a/lib/libusb/libusb20_compat01.c +++ /dev/null @@ -1,945 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2008 Hans Petter Selasky. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. - */ - -/* - * This file contains the emulation layer for LibUSB v0.1 from sourceforge. - */ - -#include - -#include -#include -#include - -#include "libusb20.h" -#include "libusb20_desc.h" -#include "libusb20_int.h" -#include "usb.h" - -/* - * The two following macros were taken from the original LibUSB v0.1 - * for sake of compatibility: - */ -#define LIST_ADD(begin, ent) \ - do { \ - if (begin) { \ - ent->next = begin; \ - ent->next->prev = ent; \ - } else { \ - ent->next = NULL; \ - } \ - ent->prev = NULL; \ - begin = ent; \ - } while(0) - -#define LIST_DEL(begin, ent) \ - do { \ - if (ent->prev) { \ - ent->prev->next = ent->next; \ - } else { \ - begin = ent->next; \ - } \ - if (ent->next) { \ - ent->next->prev = ent->prev; \ - } \ - ent->prev = NULL; \ - ent->next = NULL; \ - } while (0) - -struct usb_bus *usb_busses = NULL; - -static struct usb_bus usb_global_bus = { - .dirname = {"/dev/usb"}, - .root_dev = NULL, - .devices = NULL, -}; - -static struct libusb20_backend *usb_backend = NULL; - -struct usb_parse_state { - - struct { - struct libusb20_endpoint *currep; - struct libusb20_interface *currifc; - struct libusb20_config *currcfg; - struct libusb20_me_struct *currextra; - } a; - - struct { - struct usb_config_descriptor *currcfg; - struct usb_interface_descriptor *currifc; - struct usb_endpoint_descriptor *currep; - struct usb_interface *currifcw; - uint8_t *currextra; - } b; - - uint8_t preparse; -}; - -static struct libusb20_transfer * -usb_get_transfer_by_ep_no(usb_dev_handle * dev, uint8_t ep_no) -{ - struct libusb20_device *pdev = (void *)dev; - struct libusb20_transfer *xfer; - int err; - uint32_t bufsize; - uint8_t x; - uint8_t speed; - - x = (ep_no & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 2; - - if (ep_no & LIBUSB20_ENDPOINT_DIR_MASK) { - /* this is an IN endpoint */ - x |= 1; - } - speed = libusb20_dev_get_speed(pdev); - - /* select a sensible buffer size */ - if (speed == LIBUSB20_SPEED_LOW) { - bufsize = 256; - } else if (speed == LIBUSB20_SPEED_FULL) { - bufsize = 4096; - } else { - bufsize = 16384; - } - - xfer = libusb20_tr_get_pointer(pdev, x); - - if (xfer == NULL) - return (xfer); - - err = libusb20_tr_open(xfer, bufsize, 1, ep_no); - if (err == LIBUSB20_ERROR_BUSY) { - /* already opened */ - return (xfer); - } else if (err) { - return (NULL); - } - /* success */ - return (xfer); -} - -usb_dev_handle * -usb_open(struct usb_device *dev) -{ - int err; - - err = libusb20_dev_open(dev->dev, 16 * 2); - if (err == LIBUSB20_ERROR_BUSY) { - /* - * Workaround buggy USB applications which open the USB - * device multiple times: - */ - return (dev->dev); - } - if (err) - return (NULL); - - /* - * Dequeue USB device from backend queue so that it does not get - * freed when the backend is re-scanned: - */ - libusb20_be_dequeue_device(usb_backend, dev->dev); - - return (dev->dev); -} - -int -usb_close(usb_dev_handle * udev) -{ - struct usb_device *dev; - int err; - - err = libusb20_dev_close((void *)udev); - - if (err) - return (-1); - - if (usb_backend != NULL) { - /* - * Enqueue USB device to backend queue so that it gets freed - * when the backend is re-scanned: - */ - libusb20_be_enqueue_device(usb_backend, (void *)udev); - } else { - /* - * The backend is gone. Free device data so that we - * don't start leaking memory! - */ - dev = usb_device(udev); - libusb20_dev_free((void *)udev); - LIST_DEL(usb_global_bus.devices, dev); - free(dev); - } - return (0); -} - -int -usb_get_string(usb_dev_handle * dev, int strindex, - int langid, char *buf, size_t buflen) -{ - int err; - - err = libusb20_dev_req_string_sync((void *)dev, - strindex, langid, buf, buflen); - - if (err) - return (-1); - - return (0); -} - -int -usb_get_string_simple(usb_dev_handle * dev, int strindex, - char *buf, size_t buflen) -{ - int err; - - err = libusb20_dev_req_string_simple_sync((void *)dev, - strindex, buf, buflen); - - if (err) - return (-1); - - return (strlen(buf)); -} - -int -usb_get_descriptor_by_endpoint(usb_dev_handle * udev, int ep, uint8_t type, - uint8_t ep_index, void *buf, int size) -{ - memset(buf, 0, size); - - return (usb_control_msg(udev, ep | USB_ENDPOINT_IN, - USB_REQ_GET_DESCRIPTOR, (type << 8) + ep_index, 0, - buf, size, 1000)); -} - -int -usb_get_descriptor(usb_dev_handle * udev, uint8_t type, uint8_t desc_index, - void *buf, int size) -{ - memset(buf, 0, size); - - return (usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, - (type << 8) + desc_index, 0, buf, size, 1000)); -} - -int -usb_parse_descriptor(uint8_t *source, char *description, void *dest) -{ - uint8_t *sp = source; - uint8_t *dp = dest; - uint16_t w; - uint32_t d; - char *cp; - - for (cp = description; *cp; cp++) { - switch (*cp) { - case 'b': /* 8-bit byte */ - *dp++ = *sp++; - break; - /* - * 16-bit word, convert from little endian to CPU - */ - case 'w': - w = (sp[1] << 8) | sp[0]; - sp += 2; - /* Align to word boundary */ - dp += ((dp - (uint8_t *)0) & 1); - *((uint16_t *)dp) = w; - dp += 2; - break; - /* - * 32-bit dword, convert from little endian to CPU - */ - case 'd': - d = (sp[3] << 24) | (sp[2] << 16) | - (sp[1] << 8) | sp[0]; - sp += 4; - /* Align to word boundary */ - dp += ((dp - (uint8_t *)0) & 1); - /* Align to double word boundary */ - dp += ((dp - (uint8_t *)0) & 2); - *((uint32_t *)dp) = d; - dp += 4; - break; - } - } - return (sp - source); -} - -static void -usb_parse_extra(struct usb_parse_state *ps, uint8_t **pptr, int *plen) -{ - void *ptr; - uint16_t len; - - ptr = ps->a.currextra->ptr; - len = ps->a.currextra->len; - - if (ps->preparse == 0) { - memcpy(ps->b.currextra, ptr, len); - *pptr = ps->b.currextra; - *plen = len; - } - ps->b.currextra += len; - return; -} - -static void -usb_parse_endpoint(struct usb_parse_state *ps) -{ - struct usb_endpoint_descriptor *bep; - struct libusb20_endpoint *aep; - - aep = ps->a.currep; - bep = ps->b.currep++; - - if (ps->preparse == 0) { - /* copy descriptor fields */ - bep->bLength = aep->desc.bLength; - bep->bDescriptorType = aep->desc.bDescriptorType; - bep->bEndpointAddress = aep->desc.bEndpointAddress; - bep->bmAttributes = aep->desc.bmAttributes; - bep->wMaxPacketSize = aep->desc.wMaxPacketSize; - bep->bInterval = aep->desc.bInterval; - bep->bRefresh = aep->desc.bRefresh; - bep->bSynchAddress = aep->desc.bSynchAddress; - } - ps->a.currextra = &aep->extra; - usb_parse_extra(ps, &bep->extra, &bep->extralen); - return; -} - -static void -usb_parse_iface_sub(struct usb_parse_state *ps) -{ - struct libusb20_interface *aifc; - struct usb_interface_descriptor *bifc; - uint8_t x; - - aifc = ps->a.currifc; - bifc = ps->b.currifc++; - - if (ps->preparse == 0) { - /* copy descriptor fields */ - bifc->bLength = aifc->desc.bLength; - bifc->bDescriptorType = aifc->desc.bDescriptorType; - bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber; - bifc->bAlternateSetting = aifc->desc.bAlternateSetting; - bifc->bNumEndpoints = aifc->num_endpoints; - bifc->bInterfaceClass = aifc->desc.bInterfaceClass; - bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass; - bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol; - bifc->iInterface = aifc->desc.iInterface; - bifc->endpoint = ps->b.currep; - } - for (x = 0; x != aifc->num_endpoints; x++) { - ps->a.currep = aifc->endpoints + x; - usb_parse_endpoint(ps); - } - - ps->a.currextra = &aifc->extra; - usb_parse_extra(ps, &bifc->extra, &bifc->extralen); - return; -} - -static void -usb_parse_iface(struct usb_parse_state *ps) -{ - struct libusb20_interface *aifc; - struct usb_interface *bifc; - uint8_t x; - - aifc = ps->a.currifc; - bifc = ps->b.currifcw++; - - if (ps->preparse == 0) { - /* initialise interface wrapper */ - bifc->altsetting = ps->b.currifc; - bifc->num_altsetting = aifc->num_altsetting + 1; - } - usb_parse_iface_sub(ps); - - for (x = 0; x != aifc->num_altsetting; x++) { - ps->a.currifc = aifc->altsetting + x; - usb_parse_iface_sub(ps); - } - return; -} - -static void -usb_parse_config(struct usb_parse_state *ps) -{ - struct libusb20_config *acfg; - struct usb_config_descriptor *bcfg; - uint8_t x; - - acfg = ps->a.currcfg; - bcfg = ps->b.currcfg; - - if (ps->preparse == 0) { - /* initialise config wrapper */ - bcfg->bLength = acfg->desc.bLength; - bcfg->bDescriptorType = acfg->desc.bDescriptorType; - bcfg->wTotalLength = acfg->desc.wTotalLength; - bcfg->bNumInterfaces = acfg->num_interface; - bcfg->bConfigurationValue = acfg->desc.bConfigurationValue; - bcfg->iConfiguration = acfg->desc.iConfiguration; - bcfg->bmAttributes = acfg->desc.bmAttributes; - bcfg->MaxPower = acfg->desc.bMaxPower; - bcfg->interface = ps->b.currifcw; - } - for (x = 0; x != acfg->num_interface; x++) { - ps->a.currifc = acfg->interface + x; - usb_parse_iface(ps); - } - - ps->a.currextra = &acfg->extra; - usb_parse_extra(ps, &bcfg->extra, &bcfg->extralen); - return; -} - -int -usb_parse_configuration(struct usb_config_descriptor *config, - uint8_t *buffer) -{ - struct usb_parse_state ps; - uint8_t *ptr; - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - - if ((buffer == NULL) || (config == NULL)) { - return (-1); - } - memset(&ps, 0, sizeof(ps)); - - ps.a.currcfg = libusb20_parse_config_desc(buffer); - ps.b.currcfg = config; - if (ps.a.currcfg == NULL) { - /* could not parse config or out of memory */ - return (-1); - } - /* do the pre-parse */ - ps.preparse = 1; - usb_parse_config(&ps); - - a = ((uint8_t *)(ps.b.currifcw) - ((uint8_t *)0)); - b = ((uint8_t *)(ps.b.currifc) - ((uint8_t *)0)); - c = ((uint8_t *)(ps.b.currep) - ((uint8_t *)0)); - d = ((uint8_t *)(ps.b.currextra) - ((uint8_t *)0)); - - /* allocate memory for our configuration */ - ptr = malloc(a + b + c + d); - if (ptr == NULL) { - /* free config structure */ - free(ps.a.currcfg); - return (-1); - } - - /* "currifcw" must be first, hence this pointer is freed */ - ps.b.currifcw = (void *)(ptr); - ps.b.currifc = (void *)(ptr + a); - ps.b.currep = (void *)(ptr + a + b); - ps.b.currextra = (void *)(ptr + a + b + c); - - /* generate a libusb v0.1 compatible structure */ - ps.preparse = 0; - usb_parse_config(&ps); - - /* free config structure */ - free(ps.a.currcfg); - - return (0); /* success */ -} - -void -usb_destroy_configuration(struct usb_device *dev) -{ - uint8_t c; - - if (dev->config == NULL) { - return; - } - for (c = 0; c != dev->descriptor.bNumConfigurations; c++) { - struct usb_config_descriptor *cf = &dev->config[c]; - - if (cf->interface != NULL) { - free(cf->interface); - cf->interface = NULL; - } - } - - free(dev->config); - dev->config = NULL; - return; -} - -void -usb_fetch_and_parse_descriptors(usb_dev_handle * udev) -{ - struct usb_device *dev; - struct libusb20_device *pdev; - uint8_t *ptr; - int error; - uint32_t size; - uint16_t len; - uint8_t x; - - if (udev == NULL) { - /* be NULL safe */ - return; - } - dev = usb_device(udev); - pdev = (void *)udev; - - if (dev->descriptor.bNumConfigurations == 0) { - /* invalid device */ - return; - } - size = dev->descriptor.bNumConfigurations * - sizeof(struct usb_config_descriptor); - - dev->config = malloc(size); - if (dev->config == NULL) { - /* out of memory */ - return; - } - memset(dev->config, 0, size); - - for (x = 0; x != dev->descriptor.bNumConfigurations; x++) { - - error = (pdev->methods->get_config_desc_full) ( - pdev, &ptr, &len, x); - - if (error) { - usb_destroy_configuration(dev); - return; - } - usb_parse_configuration(dev->config + x, ptr); - - /* free config buffer */ - free(ptr); - } - return; -} - -static int -usb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size, - int timeout, int is_intr) -{ - struct libusb20_transfer *xfer; - uint32_t temp; - uint32_t maxsize; - uint32_t actlen; - char *oldbytes; - - xfer = usb_get_transfer_by_ep_no(dev, ep); - if (xfer == NULL) - return (-1); - - if (libusb20_tr_pending(xfer)) { - /* there is already a transfer ongoing */ - return (-1); - } - maxsize = libusb20_tr_get_max_total_length(xfer); - oldbytes = bytes; - - /* - * We allow transferring zero bytes which is the same - * equivalent to a zero length USB packet. - */ - do { - - temp = size; - if (temp > maxsize) { - /* find maximum possible length */ - temp = maxsize; - } - if (is_intr) - libusb20_tr_setup_intr(xfer, bytes, temp, timeout); - else - libusb20_tr_setup_bulk(xfer, bytes, temp, timeout); - - libusb20_tr_start(xfer); - - while (1) { - - if (libusb20_dev_process((void *)dev) != 0) { - /* device detached */ - return (-1); - } - if (libusb20_tr_pending(xfer) == 0) { - /* transfer complete */ - break; - } - /* wait for USB event from kernel */ - libusb20_dev_wait_process((void *)dev, -1); - } - - switch (libusb20_tr_get_status(xfer)) { - case 0: - /* success */ - break; - case LIBUSB20_TRANSFER_TIMED_OUT: - /* transfer timeout */ - return (-ETIMEDOUT); - default: - /* other transfer error */ - return (-ENXIO); - } - actlen = libusb20_tr_get_actual_length(xfer); - - bytes += actlen; - size -= actlen; - - if (actlen != temp) { - /* short transfer */ - break; - } - } while (size > 0); - - return (bytes - oldbytes); -} - -int -usb_bulk_write(usb_dev_handle * dev, int ep, char *bytes, - int size, int timeout) -{ - return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, - bytes, size, timeout, 0)); -} - -int -usb_bulk_read(usb_dev_handle * dev, int ep, char *bytes, - int size, int timeout) -{ - return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, - bytes, size, timeout, 0)); -} - -int -usb_interrupt_write(usb_dev_handle * dev, int ep, char *bytes, - int size, int timeout) -{ - return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK, - bytes, size, timeout, 1)); -} - -int -usb_interrupt_read(usb_dev_handle * dev, int ep, char *bytes, - int size, int timeout) -{ - return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK, - bytes, size, timeout, 1)); -} - -int -usb_control_msg(usb_dev_handle * dev, int requesttype, int request, - int value, int wIndex, char *bytes, int size, int timeout) -{ - struct LIBUSB20_CONTROL_SETUP_DECODED req; - int err; - uint16_t actlen; - - LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); - - req.bmRequestType = requesttype; - req.bRequest = request; - req.wValue = value; - req.wIndex = wIndex; - req.wLength = size; - - err = libusb20_dev_request_sync((void *)dev, &req, bytes, - &actlen, timeout, 0); - - if (err) - return (-1); - - return (actlen); -} - -int -usb_set_configuration(usb_dev_handle * udev, int bConfigurationValue) -{ - struct usb_device *dev; - int err; - uint8_t i; - - /* - * Need to translate from "bConfigurationValue" to - * configuration index: - */ - - if (bConfigurationValue == 0) { - /* unconfigure */ - i = 255; - } else { - /* lookup configuration index */ - dev = usb_device(udev); - - /* check if the configuration array is not there */ - if (dev->config == NULL) { - return (-1); - } - for (i = 0;; i++) { - if (i == dev->descriptor.bNumConfigurations) { - /* "bConfigurationValue" not found */ - return (-1); - } - if ((dev->config + i)->bConfigurationValue == - bConfigurationValue) { - break; - } - } - } - - err = libusb20_dev_set_config_index((void *)udev, i); - - if (err) - return (-1); - - return (0); -} - -int -usb_claim_interface(usb_dev_handle * dev, int interface) -{ - struct libusb20_device *pdev = (void *)dev; - - pdev->claimed_interface = interface; - - return (0); -} - -int -usb_release_interface(usb_dev_handle * dev, int interface) -{ - /* do nothing */ - return (0); -} - -int -usb_set_altinterface(usb_dev_handle * dev, int alternate) -{ - struct libusb20_device *pdev = (void *)dev; - int err; - uint8_t iface; - - iface = pdev->claimed_interface; - - err = libusb20_dev_set_alt_index((void *)dev, iface, alternate); - - if (err) - return (-1); - - return (0); -} - -int -usb_resetep(usb_dev_handle * dev, unsigned int ep) -{ - /* emulate an endpoint reset through clear-STALL */ - return (usb_clear_halt(dev, ep)); -} - -int -usb_clear_halt(usb_dev_handle * dev, unsigned int ep) -{ - struct libusb20_transfer *xfer; - - xfer = usb_get_transfer_by_ep_no(dev, ep); - if (xfer == NULL) - return (-1); - - libusb20_tr_clear_stall_sync(xfer); - - return (0); -} - -int -usb_reset(usb_dev_handle * dev) -{ - int err; - - err = libusb20_dev_reset((void *)dev); - - if (err) - return (-1); - - /* - * Be compatible with LibUSB from sourceforge and close the - * handle after reset! - */ - return (usb_close(dev)); -} - -int -usb_check_connected(usb_dev_handle * dev) -{ - int err; - - err = libusb20_dev_check_connected((void *)dev); - - if (err) - return (-1); - - return (0); -} - -const char * -usb_strerror(void) -{ - /* TODO */ - return ("Unknown error"); -} - -void -usb_init(void) -{ - /* nothing to do */ - return; -} - -void -usb_set_debug(int level) -{ - /* use kernel UGEN debugging if you need to see what is going on */ - return; -} - -int -usb_find_busses(void) -{ - usb_busses = &usb_global_bus; - return (1); -} - -int -usb_find_devices(void) -{ - struct libusb20_device *pdev; - struct usb_device *udev; - struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; - int devnum; - int err; - - /* cleanup after last device search */ - /* close all opened devices, if any */ - - while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) { - udev = pdev->privLuData; - libusb20_be_dequeue_device(usb_backend, pdev); - libusb20_dev_free(pdev); - if (udev != NULL) { - LIST_DEL(usb_global_bus.devices, udev); - free(udev); - } - } - - /* free old USB backend, if any */ - - libusb20_be_free(usb_backend); - - /* do a new backend device search */ - usb_backend = libusb20_be_alloc_default(); - if (usb_backend == NULL) { - return (-1); - } - /* iterate all devices */ - - devnum = 1; - pdev = NULL; - while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) { - udev = malloc(sizeof(*udev)); - if (udev == NULL) - break; - - memset(udev, 0, sizeof(*udev)); - - udev->bus = &usb_global_bus; - - snprintf(udev->filename, sizeof(udev->filename), - "/dev/ugen%u.%u", - libusb20_dev_get_bus_number(pdev), - libusb20_dev_get_address(pdev)); - - ddesc = libusb20_dev_get_device_desc(pdev); - - udev->descriptor.bLength = sizeof(udev->descriptor); - udev->descriptor.bDescriptorType = ddesc->bDescriptorType; - udev->descriptor.bcdUSB = ddesc->bcdUSB; - udev->descriptor.bDeviceClass = ddesc->bDeviceClass; - udev->descriptor.bDeviceSubClass = ddesc->bDeviceSubClass; - udev->descriptor.bDeviceProtocol = ddesc->bDeviceProtocol; - udev->descriptor.bMaxPacketSize0 = ddesc->bMaxPacketSize0; - udev->descriptor.idVendor = ddesc->idVendor; - udev->descriptor.idProduct = ddesc->idProduct; - udev->descriptor.bcdDevice = ddesc->bcdDevice; - udev->descriptor.iManufacturer = ddesc->iManufacturer; - udev->descriptor.iProduct = ddesc->iProduct; - udev->descriptor.iSerialNumber = ddesc->iSerialNumber; - udev->descriptor.bNumConfigurations = - ddesc->bNumConfigurations; - if (udev->descriptor.bNumConfigurations > USB_MAXCONFIG) { - /* truncate number of configurations */ - udev->descriptor.bNumConfigurations = USB_MAXCONFIG; - } - udev->devnum = devnum++; - /* link together the two structures */ - udev->dev = pdev; - pdev->privLuData = udev; - - err = libusb20_dev_open(pdev, 0); - if (err == 0) { - /* XXX get all config descriptors by default */ - usb_fetch_and_parse_descriptors((void *)pdev); - libusb20_dev_close(pdev); - } - LIST_ADD(usb_global_bus.devices, udev); - } - - return (devnum - 1); /* success */ -} - -struct usb_device * -usb_device(usb_dev_handle * dev) -{ - struct libusb20_device *pdev; - - pdev = (void *)dev; - - return (pdev->privLuData); -} - -struct usb_bus * -usb_get_busses(void) -{ - return (usb_busses); -} diff --git a/lib/libusb/libusb20_int.h b/lib/libusb/libusb20_int.h index 2ecfb47..bef4d02 100644 --- a/lib/libusb/libusb20_int.h +++ b/lib/libusb/libusb20_int.h @@ -226,6 +226,8 @@ struct libusb20_device { uint8_t usb_mode; uint8_t usb_speed; uint8_t is_opened; + uint8_t parent_address; + uint8_t parent_port; char usb_desc[96]; }; diff --git a/lib/libusb/libusb20_ugen20.c b/lib/libusb/libusb20_ugen20.c index 933d728..307ed96 100644 --- a/lib/libusb/libusb20_ugen20.c +++ b/lib/libusb/libusb20_ugen20.c @@ -195,6 +195,11 @@ ugen20_enumerate(struct libusb20_device *pdev, const char *id) break; } + /* get parent HUB index and port */ + + pdev->parent_address = devinfo.udi_hubindex; + pdev->parent_port = devinfo.udi_hubport; + /* generate a nice description for printout */ snprintf(pdev->usb_desc, sizeof(pdev->usb_desc), -- cgit v1.1 From 2fc0709750868aee2c2e362f8a30cba847c839e9 Mon Sep 17 00:00:00 2001 From: adrian Date: Fri, 24 Jun 2011 12:30:43 +0000 Subject: Import one of the two missing US FCC DFS bands to FCC3. The FCC opened up this band sometime in 2009 (and ath was updated); but regdomain.xml wasn't updated. --- etc/regdomain.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/etc/regdomain.xml b/etc/regdomain.xml index d95000c..ed25056 100644 --- a/etc/regdomain.xml +++ b/etc/regdomain.xml @@ -138,6 +138,12 @@ 17 + + 20 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + 23 IEEE80211_CHAN_PASSIVE @@ -176,6 +182,20 @@ IEEE80211_CHAN_HT40 + + 20 + IEEE80211_CHAN_HT20 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + + + 20 + IEEE80211_CHAN_HT40 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + 23 IEEE80211_CHAN_HT20 -- cgit v1.1 From 3ad0a92f4d34276bfcf5d92531292d85a64028ed Mon Sep 17 00:00:00 2001 From: adrian Date: Fri, 24 Jun 2011 12:31:36 +0000 Subject: Fix an incorrect frequency band for HT/40 in the FCC SKU. Noticed by: bschmidt@ --- etc/regdomain.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/regdomain.xml b/etc/regdomain.xml index ed25056..5d89846 100644 --- a/etc/regdomain.xml +++ b/etc/regdomain.xml @@ -83,7 +83,7 @@ IEEE80211_CHAN_HT20 - + 30 IEEE80211_CHAN_G IEEE80211_CHAN_HT40 -- cgit v1.1 From d8f01da7c690c2df9e0731bf4331c8e36779ffa8 Mon Sep 17 00:00:00 2001 From: adrian Date: Fri, 24 Jun 2011 12:50:18 +0000 Subject: More incorrect HT/40 setups in FCC. Noticed-by: bschmidt@ --- etc/regdomain.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/regdomain.xml b/etc/regdomain.xml index 5d89846..9f7a7a3 100644 --- a/etc/regdomain.xml +++ b/etc/regdomain.xml @@ -96,7 +96,7 @@ IEEE80211_CHAN_HT20 - + 17 IEEE80211_CHAN_HT40 @@ -106,7 +106,7 @@ IEEE80211_CHAN_HT20 - + 23 IEEE80211_CHAN_HT40 -- cgit v1.1 From f235f56e2dcd38914adc44d77fd514cf732341a8 Mon Sep 17 00:00:00 2001 From: glebius Date: Fri, 24 Jun 2011 12:55:16 +0000 Subject: Actually, if code had followed style(9), there would be less stupid errors like the one fixed in r223416. Noticed by: julian --- sbin/ipfw/nat.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c index efadeba..c95a625 100644 --- a/sbin/ipfw/nat.c +++ b/sbin/ipfw/nat.c @@ -738,7 +738,8 @@ ipfw_config_nat(int ac, char **av) char *id, *buf, **av1, *end; size_t len; - av++; ac--; + av++; + ac--; /* Nat id. */ if (ac == 0) errx(EX_DATAERR, "missing nat id"); @@ -746,7 +747,8 @@ ipfw_config_nat(int ac, char **av) i = (int)strtol(id, &end, 0); if (i <= 0 || *end != '\0') errx(EX_DATAERR, "illegal nat id: %s", id); - av++; ac--; + av++; + ac--; if (ac == 0) errx(EX_DATAERR, "missing option"); @@ -755,11 +757,13 @@ ipfw_config_nat(int ac, char **av) av1 = av; while (ac1 > 0) { tok = match_token(nat_params, *av1); - ac1--; av1++; + ac1--; + av1++; switch (tok) { case TOK_IP: case TOK_IF: - ac1--; av1++; + ac1--; + av1++; break; case TOK_ALOG: case TOK_DENY_INC: @@ -775,18 +779,22 @@ ipfw_config_nat(int ac, char **av) errx(EX_DATAERR, "redirect_addr: " "not enough arguments"); len += estimate_redir_addr(&ac1, &av1); - av1 += 2; ac1 -= 2; + av1 += 2; + ac1 -= 2; break; case TOK_REDIR_PORT: if (ac1 < 3) errx(EX_DATAERR, "redirect_port: " "not enough arguments"); - av1++; ac1--; + av1++; + ac1--; len += estimate_redir_port(&ac1, &av1); - av1 += 2; ac1 -= 2; + av1 += 2; + ac1 -= 2; /* Skip optional remoteIP/port */ if (ac1 != 0 && isdigit(**av1)) { - av1++; ac1--; + av1++; + ac1--; } break; case TOK_REDIR_PROTO: @@ -794,13 +802,16 @@ ipfw_config_nat(int ac, char **av) errx(EX_DATAERR, "redirect_proto: " "not enough arguments"); len += sizeof(struct cfg_redir); - av1 += 2; ac1 -= 2; + av1 += 2; + ac1 -= 2; /* Skip optional remoteIP/port */ if (ac1 != 0 && isdigit(**av1)) { - av1++; ac1--; + av1++; + ac1--; } if (ac1 != 0 && isdigit(**av1)) { - av1++; ac1--; + av1++; + ac1--; } break; default: @@ -819,7 +830,8 @@ ipfw_config_nat(int ac, char **av) while (ac > 0) { tok = match_token(nat_params, *av); - ac--; av++; + ac--; + av++; switch (tok) { case TOK_IP: if (ac == 0) @@ -827,13 +839,15 @@ ipfw_config_nat(int ac, char **av) if (!inet_aton(av[0], &(n->ip))) errx(EX_DATAERR, "bad ip address ``%s''", av[0]); - ac--; av++; + ac--; + av++; break; case TOK_IF: if (ac == 0) errx(EX_DATAERR, "missing option"); set_addr_dynamic(av[0], n); - ac--; av++; + ac--; + av++; break; case TOK_ALOG: n->mode |= PKT_ALIAS_LOG; @@ -912,7 +926,8 @@ ipfw_show_nat(int ac, char **av) data = NULL; frule = 0; lrule = IPFW_DEFAULT_RULE; /* max ipfw rule number */ - ac--; av++; + ac--; + av++; if (co.test_only) return; -- cgit v1.1 From 645280f5155e4aed759867707b61f2449996450e Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 24 Jun 2011 13:58:56 +0000 Subject: Typo. --- sys/dev/acpica/acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 84f65bd..9352be9 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -1244,7 +1244,7 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid, /* * First attempt at allocating the resource. For direct children, * use resource_list_alloc() to handle reserved resources. For - * other dveices, pass the request up to our parent. + * other devices, pass the request up to our parent. */ if (bus == device_get_parent(child)) { ad = device_get_ivars(child); -- cgit v1.1 From 3ccba4a3afed2444d30b434b3ec285eced3c286a Mon Sep 17 00:00:00 2001 From: adrian Date: Fri, 24 Jun 2011 14:31:30 +0000 Subject: Fix another broken HT40 channel band reference. --- etc/regdomain.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/regdomain.xml b/etc/regdomain.xml index 9f7a7a3..5e98dea 100644 --- a/etc/regdomain.xml +++ b/etc/regdomain.xml @@ -251,7 +251,7 @@ IEEE80211_CHAN_HT20 - + 30 IEEE80211_CHAN_G IEEE80211_CHAN_HT40 -- cgit v1.1 From d77535edb69e85936620addc80ca253da18f745e Mon Sep 17 00:00:00 2001 From: jonathan Date: Fri, 24 Jun 2011 14:40:22 +0000 Subject: Tidy up a capabilities-related comment. This comment refers to an #ifdef that hasn't been merged [yet?]; remove it. Approved by: rwatson --- sys/kern/vfs_subr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 741061d..c5ae83c 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -3590,9 +3590,6 @@ vn_isdisk(struct vnode *vp, int *errp) * and optional call-by-reference privused argument allowing vaccess() * to indicate to the caller whether privilege was used to satisfy the * request (obsoleted). Returns 0 on success, or an errno on failure. - * - * The ifdef'd CAPABILITIES version is here for reference, but is not - * actually used. */ int vaccess(enum vtype type, mode_t file_mode, uid_t file_uid, gid_t file_gid, -- cgit v1.1 From 71e30a51e834d75c8872df99e10b3fe4762ef6c2 Mon Sep 17 00:00:00 2001 From: pluknet Date: Fri, 24 Jun 2011 14:56:38 +0000 Subject: Add support for string values with white spaces for ifconfig(8) parameters accepting them (such as description, group). Changes discussed on freebsd-rc. PR: conf/156675 Reported by: "Alexander V. Chernikov" Suggested by: hrs Analyzed with: Alexander V. Chernikov via IRC MFC after: 2 weeks --- etc/network.subr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/network.subr b/etc/network.subr index f9a1f88..44a5892 100644 --- a/etc/network.subr +++ b/etc/network.subr @@ -94,7 +94,7 @@ ifconfig_up() # ifconfig_IF ifconfig_args=`ifconfig_getargs $1` if [ -n "${ifconfig_args}" ]; then - ifconfig $1 ${ifconfig_args} + eval ifconfig $1 ${ifconfig_args} _cfg=0 fi -- cgit v1.1 From 9d967b99869b118187f3816f87034a110428a848 Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 24 Jun 2011 17:54:45 +0000 Subject: Don't die if either of INET or INET6 aren't in the running kernel. Instead, report "protocol not supported" errors at runtime if a user attempts to use a protocol that the kernel doesn't support. Reviewed by: bz MFC after: 1 week --- usr.sbin/mtest/mtest.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/usr.sbin/mtest/mtest.c b/usr.sbin/mtest/mtest.c index 442c3c4..60f7e09 100644 --- a/usr.sbin/mtest/mtest.c +++ b/usr.sbin/mtest/mtest.c @@ -204,14 +204,16 @@ main(int argc, char **argv) s6 = -1; #ifdef INET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (s == -1) + if (s == -1 && errno != EPROTONOSUPPORT) err(1, "can't open IPv4 socket"); #endif #ifdef INET6 s6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (s6 == -1) + if (s6 == -1 && errno != EPROTONOSUPPORT) err(1, "can't open IPv6 socket"); #endif + if (s == -1 && s6 == -1) + errc(1, EPROTONOSUPPORT, "can't open socket"); if (argc < 2) { if (isatty(STDIN_FILENO)) { @@ -371,7 +373,7 @@ af2socklen(const int af) } static void -process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused) +process_cmd(char *cmd, int s, int s6, FILE *fp __unused) { char str1[STR_SIZE]; char str2[STR_SIZE]; @@ -457,7 +459,10 @@ process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused) optval = (void *)&mr.mr; optlen = sizeof(mr.mr); } - if (setsockopt(s, level, optname, optval, + if (s < 0) { + warnc(EPROTONOSUPPORT, "setsockopt %s", + toptname); + } else if (setsockopt(s, level, optname, optval, optlen) == 0) { printf("ok\n"); break; @@ -496,7 +501,10 @@ process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused) optval = (void *)&mr.mr6; optlen = sizeof(mr.mr6); } - if (setsockopt(s6, level, optname, optval, + if (s6 < 0) { + warnc(EPROTONOSUPPORT, "setsockopt %s", + toptname); + } else if (setsockopt(s6, level, optname, optval, optlen) == 0) { printf("ok\n"); break; @@ -534,6 +542,10 @@ process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused) break; } af = su.sa.sa_family; + if (af2sock(af, s, s6) == -1) { + warnc(EPROTONOSUPPORT, "setsourcefilter"); + break; + } memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_NUMERICHOST; @@ -593,6 +605,10 @@ process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused) break; } af = su.sa.sa_family; + if (af2sock(af, s, s6) == -1) { + warnc(EPROTONOSUPPORT, "getsourcefilter"); + break; + } /* First determine our current filter mode. */ n = 0; @@ -700,6 +716,10 @@ process_cmd(char *cmd, int s, int s6 __unused, FILE *fp __unused) } af = su.sa.sa_family; + if (af2sock(af, s, s6) == -1) { + warnc(EPROTONOSUPPORT, "getsourcefilter"); + break; + } nsrc = nreqsrc; if (getsourcefilter(af2sock(af, s, s6), ifindex, &su.sa, su.sa.sa_len, &fmode, &nsrc, &sources[0].ss) != 0) { -- cgit v1.1 From 9fee05c0d9060f4a70a62c23c55eae9a40a1a153 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 18:11:55 +0000 Subject: - Export the URIO USB device ID's. - Add checks for configuration and interface index. MFC after: 3 days --- sys/dev/usb/storage/urio.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/sys/dev/usb/storage/urio.c b/sys/dev/usb/storage/urio.c index ee93439..6687173 100644 --- a/sys/dev/usb/storage/urio.c +++ b/sys/dev/usb/storage/urio.c @@ -198,22 +198,25 @@ DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, NULL, 0); MODULE_DEPEND(urio, usb, 1, 1, 1); MODULE_VERSION(urio, 1); +static const STRUCT_USB_HOST_ID urio_devs[] = { + {USB_VPI(USB_VENDOR_DIAMOND, USB_PRODUCT_DIAMOND_RIO500USB, 0)}, + {USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO600USB, 0)}, + {USB_VPI(USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO800USB, 0)}, +}; + static int urio_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); - if (uaa->usb_mode != USB_MODE_HOST) { + if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); - } - if ((((uaa->info.idVendor == USB_VENDOR_DIAMOND) && - (uaa->info.idProduct == USB_PRODUCT_DIAMOND_RIO500USB)) || - ((uaa->info.idVendor == USB_VENDOR_DIAMOND2) && - ((uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO600USB) || - (uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO800USB))))) - return (0); - else + if (uaa->info.bConfigIndex != 0) return (ENXIO); + if (uaa->info.bIfaceIndex != 0) + return (ENXIO); + + return (usbd_lookup_id_by_uaa(urio_devs, sizeof(urio_devs), uaa)); } static int -- cgit v1.1 From a551321476aed54765a889e3b29a2a3781561950 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 18:14:43 +0000 Subject: - Move execution of event handlers into the probe and attach function so that dynamically loaded device drivers get a chance to run their event hooks. - Decouple the USB suspend and resume lock from witness. It produces some false warnings due to reusing the lock name among multiple devices. MFC after: 3 days --- sys/dev/usb/usb_device.c | 22 ++++++++++++++++------ sys/dev/usb/usb_msctest.c | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 893e79d..76c976b 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -1297,6 +1297,21 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index) usb_init_attach_arg(udev, &uaa); + /* + * If the whole USB device is targeted, invoke the USB event + * handler(s): + */ + if (iface_index == USB_IFACE_INDEX_ANY) { + + EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa); + + if (uaa.dev_state != UAA_DEV_READY) { + /* leave device unconfigured */ + usb_unconfigure(udev, 0); + goto done; + } + } + /* Check if only one interface should be probed: */ if (iface_index != USB_IFACE_INDEX_ANY) { i = iface_index; @@ -1526,7 +1541,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus, /* initialise our SX-lock */ sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK); - sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_DUPOK); + sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS); cv_init(&udev->ctrlreq_cv, "WCTRL"); cv_init(&udev->ref_cv, "UGONE"); @@ -1834,11 +1849,6 @@ repeat_set_config: } } } - EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa); - if (uaa.dev_state != UAA_DEV_READY) { - /* leave device unconfigured */ - usb_unconfigure(udev, 0); - } config_done: DPRINTF("new dev (addr %d), udev=%p, parent_hub=%p\n", diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c index 909615e..45bd363 100644 --- a/sys/dev/usb/usb_msctest.c +++ b/sys/dev/usb/usb_msctest.c @@ -489,6 +489,24 @@ bbb_attach(struct usb_device *udev, uint8_t iface_index) struct usb_interface_descriptor *id; struct bbb_transfer *sc; usb_error_t err; + uint8_t do_unlock; + + /* automatic locking */ + if (usbd_enum_is_locked(udev)) { + do_unlock = 0; + } else { + do_unlock = 1; + usbd_enum_lock(udev); + } + + /* + * Make sure any driver which is hooked up to this interface, + * like umass is gone: + */ + usb_detach_device(udev, iface_index, 0); + + if (do_unlock) + usbd_enum_unlock(udev); iface = usbd_get_iface(udev, iface_index); if (iface == NULL) -- cgit v1.1 From ccf732af88ac42a2b291b4e8139c70efbca3494f Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 19:02:56 +0000 Subject: - Ensure that we get all the required nomatch devd events. MFC after: 3 days --- sys/dev/usb/usb_device.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index 76c976b..932c022 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -1358,17 +1358,18 @@ usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index) uaa.info.bIfaceIndex, uaa.info.bIfaceNum); - if (usb_probe_and_attach_sub(udev, &uaa)) { - /* ignore */ - } - } + usb_probe_and_attach_sub(udev, &uaa); - if (uaa.temp_dev) { - /* remove the last created child; it is unused */ - - if (device_delete_child(udev->parent_dev, uaa.temp_dev)) { + /* + * Remove the leftover child, if any, to enforce that + * a new nomatch devd event is generated for the next + * interface if no driver is found: + */ + if (uaa.temp_dev == NULL) + continue; + if (device_delete_child(udev->parent_dev, uaa.temp_dev)) DPRINTFN(0, "device delete child failed\n"); - } + uaa.temp_dev = NULL; } done: if (do_unlock) -- cgit v1.1 From 72142e46137809c92085360ce8a3ea21853b1424 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 19:32:29 +0000 Subject: - Export more USB device ID's. MFC after: 3 days --- sys/dev/usb/misc/udbp.c | 41 ++++++++++++++--------------------------- sys/dev/usb/misc/ufm.c | 18 +++++++++++------- sys/dev/usb/serial/ufoma.c | 30 ++++++++++++++++++------------ sys/dev/usb/serial/umodem.c | 9 ++++++--- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/sys/dev/usb/misc/udbp.c b/sys/dev/usb/misc/udbp.c index 38a4fee..1a72cae 100644 --- a/sys/dev/usb/misc/udbp.c +++ b/sys/dev/usb/misc/udbp.c @@ -288,40 +288,27 @@ udbp_modload(module_t mod, int event, void *data) return (error); } +static const STRUCT_USB_HOST_ID udbp_devs[] = { + {USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_TURBOCONNECT, 0)}, + {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301, 0)}, + {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302, 0)}, + {USB_VPI(USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_EZLINK, 0)}, + {USB_VPI(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL620USB, 0)}, +}; + static int udbp_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); - if (uaa->usb_mode != USB_MODE_HOST) { + if (uaa->usb_mode != USB_MODE_HOST) + return (ENXIO); + if (uaa->info.bConfigIndex != 0) + return (ENXIO); + if (uaa->info.bIfaceIndex != 0) return (ENXIO); - } - /* - * XXX Julian, add the id of the device if you have one to test - * things with. run 'usbdevs -v' and note the 3 ID's that appear. - * The Vendor Id and Product Id are in hex and the Revision Id is in - * bcd. But as usual if the revision is 0x101 then you should - * compare the revision id in the device descriptor with 0x101 Or go - * search the file usbdevs.h. Maybe the device is already in there. - */ - if (((uaa->info.idVendor == USB_VENDOR_NETCHIP) && - (uaa->info.idProduct == USB_PRODUCT_NETCHIP_TURBOCONNECT))) - return (0); - - if (((uaa->info.idVendor == USB_VENDOR_PROLIFIC) && - ((uaa->info.idProduct == USB_PRODUCT_PROLIFIC_PL2301) || - (uaa->info.idProduct == USB_PRODUCT_PROLIFIC_PL2302)))) - return (0); - - if ((uaa->info.idVendor == USB_VENDOR_ANCHOR) && - (uaa->info.idProduct == USB_PRODUCT_ANCHOR_EZLINK)) - return (0); - - if ((uaa->info.idVendor == USB_VENDOR_GENESYS) && - (uaa->info.idProduct == USB_PRODUCT_GENESYS_GL620USB)) - return (0); - return (ENXIO); + return (usbd_lookup_id_by_uaa(udbp_devs, sizeof(udbp_devs), uaa)); } static int diff --git a/sys/dev/usb/misc/ufm.c b/sys/dev/usb/misc/ufm.c index 75e2b7f..11bea65 100644 --- a/sys/dev/usb/misc/ufm.c +++ b/sys/dev/usb/misc/ufm.c @@ -118,19 +118,23 @@ DRIVER_MODULE(ufm, uhub, ufm_driver, ufm_devclass, NULL, 0); MODULE_DEPEND(ufm, usb, 1, 1, 1); MODULE_VERSION(ufm, 1); +static const STRUCT_USB_HOST_ID ufm_devs[] = { + {USB_VPI(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_FMRADIO, 0)}, +}; + static int ufm_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); - if (uaa->usb_mode != USB_MODE_HOST) { + if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); - } - if ((uaa->info.idVendor == USB_VENDOR_CYPRESS) && - (uaa->info.idProduct == USB_PRODUCT_CYPRESS_FMRADIO)) { - return (0); - } - return (ENXIO); + if (uaa->info.bConfigIndex != 0) + return (ENXIO); + if (uaa->info.bIfaceIndex != 0) + return (ENXIO); + + return (usbd_lookup_id_by_uaa(ufm_devs, sizeof(ufm_devs), uaa)); } static int diff --git a/sys/dev/usb/serial/ufoma.c b/sys/dev/usb/serial/ufoma.c index a32fd47..31be85c 100644 --- a/sys/dev/usb/serial/ufoma.c +++ b/sys/dev/usb/serial/ufoma.c @@ -327,6 +327,11 @@ MODULE_DEPEND(ufoma, ucom, 1, 1, 1); MODULE_DEPEND(ufoma, usb, 1, 1, 1); MODULE_VERSION(ufoma, 1); +static const STRUCT_USB_HOST_ID ufoma_devs[] = { + {USB_IFACE_CLASS(UICLASS_CDC), + USB_IFACE_SUBCLASS(UISUBCLASS_MCPC),}, +}; + static int ufoma_probe(device_t dev) { @@ -334,30 +339,31 @@ ufoma_probe(device_t dev) struct usb_interface_descriptor *id; struct usb_config_descriptor *cd; usb_mcpc_acm_descriptor *mad; + int error; - if (uaa->usb_mode != USB_MODE_HOST) { + if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); - } + + error = usbd_lookup_id_by_uaa(ufoma_devs, sizeof(ufoma_devs), uaa); + if (error) + return (error); + id = usbd_get_interface_descriptor(uaa->iface); cd = usbd_get_config_descriptor(uaa->device); - if ((id == NULL) || - (cd == NULL) || - (id->bInterfaceClass != UICLASS_CDC) || - (id->bInterfaceSubClass != UISUBCLASS_MCPC)) { + if (id == NULL || cd == NULL) return (ENXIO); - } + mad = ufoma_get_intconf(cd, id, UDESC_VS_INTERFACE, UDESCSUB_MCPC_ACM); - if (mad == NULL) { + if (mad == NULL) return (ENXIO); - } + #ifndef UFOMA_HANDSFREE if ((mad->bType == UMCPC_ACM_TYPE_AB5) || - (mad->bType == UMCPC_ACM_TYPE_AB6)) { + (mad->bType == UMCPC_ACM_TYPE_AB6)) return (ENXIO); - } #endif - return (0); + return (BUS_PROBE_GENERIC); } static int diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c index 92bfe93..ed5162f 100644 --- a/sys/dev/usb/serial/umodem.c +++ b/sys/dev/usb/serial/umodem.c @@ -276,11 +276,14 @@ umodem_probe(device_t dev) DPRINTFN(11, "\n"); - if (uaa->usb_mode != USB_MODE_HOST) { + if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); - } + error = usbd_lookup_id_by_uaa(umodem_devs, sizeof(umodem_devs), uaa); - return (error); + if (error) + return (error); + + return (BUS_PROBE_GENERIC); } static int -- cgit v1.1 From f5e9daf260f37151cc8e3c60b75612ca9ff3352c Mon Sep 17 00:00:00 2001 From: jilles Date: Fri, 24 Jun 2011 20:23:50 +0000 Subject: sh(1): Document the case command better. Suggested by: netchild Reviewed by: gjb --- bin/sh/sh.1 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index e318216..bb101336 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd June 18, 2011 +.Dd June 24, 2011 .Dt SH 1 .Os .Sh NAME @@ -994,11 +994,22 @@ described later), separated by .Ql \&| characters. +Tilde expansion, parameter expansion, command substitution, +arithmetic expansion and quote removal are applied to the word. +Then, each pattern is expanded in turn using tilde expansion, +parameter expansion, command substitution and arithmetic expansion and +the expanded form of the word is checked against it. +If a match is found, the corresponding list is executed. If the selected list is terminated by the control operator .Ql ;& instead of .Ql ;; , -execution continues with the next list. +execution continues with the next list, +continuing until a list terminated with +.Ql ;; +or the end of the +.Ic case +command. The exit code of the .Ic case command is the exit code of the last command executed in the list or -- cgit v1.1 From 99e5945c1699988d03ad2ae09d005e3e2b53eca4 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 21:27:33 +0000 Subject: - We need to sort all USB device ID's together. Else the matching order will be wrong. This is required because devd only executes one entry. MFC after: 14 days --- tools/tools/bus_autoconf/bus_autoconf.c | 151 +++++++++++++++++++++++-------- tools/tools/bus_autoconf/bus_autoconf.h | 3 + tools/tools/bus_autoconf/bus_autoconf.sh | 63 +++++++++---- 3 files changed, 163 insertions(+), 54 deletions(-) diff --git a/tools/tools/bus_autoconf/bus_autoconf.c b/tools/tools/bus_autoconf/bus_autoconf.c index 38fbd29..3ddab5a 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.c +++ b/tools/tools/bus_autoconf/bus_autoconf.c @@ -43,15 +43,67 @@ static char *type; static char *file_name; -static char *module; static const char *mode; +struct usb_info; +static void usb_dump_sub(struct usb_device_id *, struct usb_info *); + +/* + * To ensure that the correct USB driver is loaded, the driver having + * the most information about the device must be probed first. Then + * more generic drivers shall be probed. + */ static int usb_compare(const void *_a, const void *_b) { const struct usb_device_id *a = _a; const struct usb_device_id *b = _b; + /* vendor matches first */ + + if (a->match_flag_vendor > b->match_flag_vendor) + return (-1); + if (a->match_flag_vendor < b->match_flag_vendor) + return (1); + + /* product matches first */ + + if (a->match_flag_product > b->match_flag_product) + return (-1); + if (a->match_flag_product < b->match_flag_product) + return (1); + + /* device class matches first */ + + if (a->match_flag_dev_class > b->match_flag_dev_class) + return (-1); + if (a->match_flag_dev_class < b->match_flag_dev_class) + return (1); + + if (a->match_flag_dev_subclass > b->match_flag_dev_subclass) + return (-1); + if (a->match_flag_dev_subclass < b->match_flag_dev_subclass) + return (1); + + /* interface class matches first */ + + if (a->match_flag_int_class > b->match_flag_int_class) + return (-1); + if (a->match_flag_int_class < b->match_flag_int_class) + return (1); + + if (a->match_flag_int_subclass > b->match_flag_int_subclass) + return (-1); + if (a->match_flag_int_subclass < b->match_flag_int_subclass) + return (1); + + if (a->match_flag_int_protocol > b->match_flag_int_protocol) + return (-1); + if (a->match_flag_int_protocol < b->match_flag_int_protocol) + return (1); + + /* then sort according to value */ + if (a->idVendor > b->idVendor) return (1); if (a->idVendor < b->idVendor) @@ -85,7 +137,9 @@ usb_compare(const void *_a, const void *_b) if (a->bInterfaceProtocol < b->bInterfaceProtocol) return (-1); - return (0); + /* in the end sort by module name */ + + return (strcmp(a->module_name, b->module_name)); } static void @@ -105,39 +159,55 @@ static void usb_dump_sub(struct usb_device_id *id, struct usb_info *pinfo) { #if USB_HAVE_COMPAT_LINUX - if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) - id->match_flag_vendor = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) - id->match_flag_product = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) - id->match_flag_dev_lo = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) - id->match_flag_dev_hi = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) - id->match_flag_dev_class = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) - id->match_flag_dev_subclass = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) - id->match_flag_dev_protocol = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) - id->match_flag_int_class = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) - id->match_flag_int_subclass = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) - id->match_flag_int_protocol = 1; + if (id->match_flags != 0) { + if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) + id->match_flag_vendor = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) + id->match_flag_product = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) + id->match_flag_dev_lo = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) + id->match_flag_dev_hi = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) + id->match_flag_dev_class = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) + id->match_flag_dev_subclass = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) + id->match_flag_dev_protocol = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) + id->match_flag_int_class = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) + id->match_flag_int_subclass = 1; + if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) + id->match_flag_int_protocol = 1; + id->match_flags = 0; + } #endif + if (pinfo != NULL) { + + pinfo->is_iface = id->match_flag_int_class | + id->match_flag_int_protocol | + id->match_flag_int_subclass; + + pinfo->is_dev = id->match_flag_dev_class | + id->match_flag_dev_subclass; - pinfo->is_iface = id->match_flag_int_class | - id->match_flag_int_protocol | - id->match_flag_int_subclass; + pinfo->is_vp = id->match_flag_vendor | + id->match_flag_product; - pinfo->is_dev = id->match_flag_dev_class | - id->match_flag_dev_subclass; + pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface; + } +} - pinfo->is_vp = id->match_flag_vendor | - id->match_flag_product; +static char * +usb_trim(char *ptr) +{ + char *end; - pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface; + end = strchr(ptr, ' '); + if (end) + *end = 0; + return (ptr); } static uint32_t @@ -149,7 +219,7 @@ usb_dump(struct usb_device_id *id, uint32_t nid) usb_dump_sub(id, &info); if (info.is_any) { - printf("nomatch 10 {\n" + printf("nomatch 32 {\n" " match \"bus\" \"uhub[0-9]+\";\n" " match \"mode\" \"%s\";\n", mode); } else { @@ -212,7 +282,7 @@ usb_dump(struct usb_device_id *id, uint32_t nid) id->bInterfaceProtocol); } printf(" action \"kldload %s\";\n" - "};\n\n", module); + "};\n\n", usb_trim(id->module_name)); return (n); } @@ -239,12 +309,21 @@ usb_parse_and_dump(int f, off_t size) } nid = size / sizeof(*id); + for (x = 0; x != nid; x++) { + /* make sure flag bits are correct */ + usb_dump_sub(id + x, NULL); + /* zero terminate string */ + id[x].module_name[sizeof(id[0].module_name) - 1] = 0; + } + usb_sort(id, nid); for (x = 0; x != nid;) x += usb_dump(id + x, nid - x); free(id); + + printf("# %d %s entries processed\n\n", (int)nid, type); } static void @@ -253,7 +332,6 @@ usage(void) fprintf(stderr, "bus_autoconf - devd config file generator\n" " -i \n" - " -m \n" " -t \n" " -h show usage\n" ); @@ -263,7 +341,7 @@ usage(void) int main(int argc, char **argv) { - const char *params = "i:m:ht:"; + const char *params = "i:ht:"; int c; int f; off_t off; @@ -276,16 +354,13 @@ main(int argc, char **argv) case 't': type = optarg; break; - case 'm': - module = optarg; - break; default: usage(); break; } } - if (type == NULL || module == NULL || file_name == NULL) + if (type == NULL || file_name == NULL) usage(); f = open(file_name, O_RDONLY); diff --git a/tools/tools/bus_autoconf/bus_autoconf.h b/tools/tools/bus_autoconf/bus_autoconf.h index a247109..7dbc486 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.h +++ b/tools/tools/bus_autoconf/bus_autoconf.h @@ -33,6 +33,9 @@ struct usb_device_id { + /* Internal field */ + char module_name[32]; + /* Hook for driver specific information */ unsigned long driver_info; diff --git a/tools/tools/bus_autoconf/bus_autoconf.sh b/tools/tools/bus_autoconf/bus_autoconf.sh index 4815572..21a4df0 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.sh +++ b/tools/tools/bus_autoconf/bus_autoconf.sh @@ -29,6 +29,30 @@ OS=FreeBSD DOLLAR=$ +cleanup() +{ + # Cleanup + rm -f usb_dual.ids + rm -f usb_host.ids + rm -f usb_device.ids +} + +usb_format() +{ + [ -f ${1} ] || return + + # Split into one and one record + split -b 32 ${1} ${1}. + + # Prefix each record by the module name + for G in $(ls ${1}.*) + do + printf "%-32s" ${3} >> ${2} + cat ${G} >> ${2} + rm -f ${G} + done +} + cat < /dev/null -[ -f ${F}.ids ] && ( -bus_autoconf -i ${F}.ids -t usb_host -m ${H} ; -rm ${F}.ids -) +objcopy -j usb_host_id -O binary ${F} temp.ids 2> /dev/null +usb_format temp.ids usb_host.ids ${H} + # USB Device -objcopy -j usb_device_id -O binary ${F} ${F}.ids 2> /dev/null -[ -f ${F}.ids ] && ( -bus_autoconf -i ${F}.ids -t usb_device -m ${H} ; -rm ${F}.ids -) +objcopy -j usb_device_id -O binary ${F} temp.ids 2> /dev/null +usb_format temp.ids usb_device.ids ${H} + # USB Dual mode -objcopy -j usb_dual_id -O binary ${F} ${F}.ids 2> /dev/null -[ -f ${F}.ids ] && ( -bus_autoconf -i ${F}.ids -t usb_dual -m ${H} ; -rm ${F}.ids -) +objcopy -j usb_dual_id -O binary ${F} temp.ids 2> /dev/null +usb_format temp.ids usb_dual.ids ${H} + done + +# Dump all data +[ -f usb_dual.ids ] && bus_autoconf -i usb_dual.ids -t usb_dual +[ -f usb_host.ids ] && bus_autoconf -i usb_host.ids -t usb_host +[ -f usb_device.ids ] && bus_autoconf -i usb_device.ids -t usb_device + +# Cleanup +cleanup -- cgit v1.1 From e68086fe4990438ffb7c4cff48df0152f7ddfc11 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 21:32:03 +0000 Subject: - Add auto-load devd config file for USB kernel modules. MFC after: 14 days --- etc/devd/bus_auto.conf | 2347 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2347 insertions(+) create mode 100644 etc/devd/bus_auto.conf diff --git a/etc/devd/bus_auto.conf b/etc/devd/bus_auto.conf new file mode 100644 index 0000000..596fa7e --- /dev/null +++ b/etc/devd/bus_auto.conf @@ -0,0 +1,2347 @@ +# +# $FreeBSD$ +# +# This file was automatically generated by "tools/bus_autoconf.sh". +# Please do not edit! +# + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x06"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x0a"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x0d"; + action "kldload if_cdce"; +}; + +# 3 usb_dual entries processed + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1290"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1292"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1294"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1297"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0104"; + match "product" "0x00be"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03e8"; + match "product" "0x0008"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03eb"; + match "product" "0x2109"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x0121|0x1016|0x1116|0x1216|0x1b1d|0x1e1d|0x2016|0x2116|0x2216|0x3016|0x3116|0x3216|0x3524|0x4016|0x4116|0x4216|0x5016|0x5116|0x5216|0x811c|0xca02)"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0402"; + match "product" "0x5632"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0403"; + match "product" "(0x6001|0x6004|0x6010|0x6011|0x8372|0x9e90|0xcc48|0xcc49|0xcc4a|0xd678|0xe6c8|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xee18|0xf608|0xf60b|0xf850|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfc08|0xfc09|0xfc0b|0xfc0c|0xfc0d|0xfc82)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0408"; + match "product" "(0x0304|0x1000|0xea02|0xea03|0xea04|0xea05|0xea06)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0409"; + match "product" "(0x00d5|0x00d6|0x00d7|0x8024|0x8025)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x0001|0x0005|0x0009|0x0012|0x003d|0x005e|0x0066|0x0067|0x006e|0x008b|0x00b3|0x00d8|0x00d9|0x00da|0x00e8|0x0116|0x0119|0x012e|0x0137|0x0148|0x0150|0x015d|0x016f)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0413"; + match "product" "0x2101"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0423"; + match "product" "(0x000a|0x000c)"; + action "kldload if_cue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x043e"; + match "product" "0x9c01"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045a"; + match "product" "(0x5001|0x5002)"; + action "kldload urio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045b"; + match "product" "0x0053"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045e"; + match "product" "(0x0079|0x007a|0x00ce|0x0400|0x0401|0x0402|0x0403|0x0404|0x0405|0x0406|0x0407|0x0408|0x0409|0x040a|0x040b|0x040c|0x040d|0x040e|0x040f|0x0410|0x0411|0x0412|0x0413|0x0414|0x0415|0x0416|0x0417|0x0432|0x0433|0x0434|0x0435|0x0436|0x0437|0x0438|0x0439|0x043a|0x043b|0x043c|0x043d|0x043e|0x043f|0x0440|0x0441|0x0442|0x0443|0x0444|0x0445|0x0446|0x0447|0x0448|0x0449|0x044a|0x044b|0x044c|0x044d|0x044e|0x044f|0x0450|0x0451|0x0452|0x0453|0x0454|0x0455|0x0456|0x0457|0x0458|0x0459|0x045a|0x045b|0x045c|0x045d|0x045e|0x045f|0x0460|0x0461|0x0462|0x0463|0x0464|0x0465|0x0466|0x0467|0x0468|0x0469|0x046a|0x046b|0x046c|0x046d|0x046e|0x046f|0x0470|0x0471|0x0472|0x0473|0x0474|0x0475|0x0476|0x0477|0x0478|0x0479|0x047a|0x047b|0x04c8|0x04c9|0x04ca|0x04cb|0x04cc|0x04cd|0x04ce|0x04d7|0x04d8|0x04d9|0x04da|0x04db|0x04dc|0x04dd|0x04de|0x04df|0x04e0|0x04e1|0x04e2|0x04e3|0x04e4|0x04e5|0x04e6|0x04e7|0x04e8|0x04e9|0x04ea)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0471"; + match "product" "(0x066a|0x1236|0x200f)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0482"; + match "product" "0x0203"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0489"; + match "product" "(0xe000|0xe003)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x049f"; + match "product" "(0x0003|0x0032|0x505a)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a4"; + match "product" "0x0014"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a5"; + match "product" "(0x4027|0x4068)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04ad"; + match "product" "(0x0301|0x0302|0x0303|0x0306)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b4"; + match "product" "0x1002"; + action "kldload ufm"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b7"; + match "product" "0x0531"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b8"; + match "product" "(0x0521|0x0522)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "(0x0901|0x0904|0x0913|0x0930|0x0944|0x0945|0x0947|0x0948|0x0a03|0x0a0e)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bf"; + match "product" "(0x0115|0x0117)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04c5"; + match "product" "(0x1058|0x1079)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04da"; + match "product" "(0x2500|0x3900)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04dd"; + match "product" "(0x8004|0x8005|0x8006|0x8007|0x9031|0x9102|0x9121|0x9123|0x9151|0x91ac|0x9242)"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "(0x5f00|0x5f01|0x5f02|0x5f03|0x5f04|0x6601|0x6611|0x6613|0x6615|0x6617|0x6619|0x661b|0x662e|0x6630|0x6632|0x8001)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04f1"; + match "product" "(0x3008|0x3011|0x3012)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0502"; + match "product" "(0x1631|0x1632|0x16e1|0x16e2|0x16e3)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0506"; + match "product" "(0x03e8|0x11f8|0x4601)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "(0x0103|0x0109|0x0121|0x0257|0x0409|0x1203|0x4050|0x5055|0x7050|0x7050|0x7051|0x705a|0x705c|0x705e|0x8053|0x805c|0x815c|0x825a|0x905b|0x935a)"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0525"; + match "product" "(0x1080|0xa4a2)"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0536"; + match "product" "0x01a0"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0543"; + match "product" "(0x0ed9|0x1527|0x1529|0x152b|0x152e|0x1921|0x1922|0x1923)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0547"; + match "product" "(0x2008|0x2720)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x054c"; + match "product" "(0x0038|0x0066|0x0095|0x009a|0x00da|0x0169|0x0437)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "(0x2002|0x2007|0x2008|0x2009|0x4000)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x055d"; + match "product" "0x2018"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0565"; + match "product" "(0x0001|0x0002|0x0003|0x0005)"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0567"; + match "product" "(0x2000|0x2002)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056c"; + match "product" "0x8007"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "(0x200c|0x4002|0x4005|0x400b|0x4010|0x5003|0x5004|0xabc1)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x057c"; + match "product" "(0x2200|0x3800)"; + action "kldload ng_ubt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0584"; + match "product" "(0xb000|0xb020)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0586"; + match "product" "(0x3401|0x3407|0x3409|0x340a|0x340f|0x3410|0x3416|0x341a)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x058f"; + match "product" "0x9720"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05a6"; + match "product" "0x0101"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "(0x020d|0x020e|0x020f|0x0215|0x0217|0x0218|0x0219|0x021a|0x021b|0x021c|0x0229|0x022a|0x022b|0x030a|0x030b|0x1402)"; + action "kldload atp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ad"; + match "product" "0x0fba"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05c6"; + match "product" "(0x6000|0x6613)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05cc"; + match "product" "0x3000"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05db"; + match "product" "(0x0003|0x0005|0x0009|0x000a|0x0011)"; + action "kldload uvscom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e0"; + match "product" "(0x2000|0x2001|0x2002|0x2003|0x2004|0x2005|0x2006|0x2007|0x2008|0x2009|0x200a)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e3"; + match "product" "0x0501"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e9"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x066b"; + match "product" "(0x200c|0x2202|0x2202|0x2203|0x2204|0x2206|0x400b)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0675"; + match "product" "0x0550"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "(0x0000|0x0001|0x04bb|0x0609|0x0611|0x0612|0x1234|0x206a|0x2303|0x2501|0x331a|0xaaa0|0xaaa2)"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067c"; + match "product" "0x1001"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067e"; + match "product" "0x1001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0681"; + match "product" "0x3c06"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06e1"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06f8"; + match "product" "(0xe000|0xe010|0xe020|0xe030)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "(0x0100|0x0200|0x0201|0xee13|0xee13)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0711"; + match "product" "(0x0200|0x0210|0x0230)"; + action "kldload umct"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0731"; + match "product" "(0x0528|0x2003)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0745"; + match "product" "(0x0001|0x1000)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0769"; + match "product" "(0x11f2|0x11f3|0x31f3)"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x077b"; + match "product" "0x2226"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0789"; + match "product" "(0x010c|0x0160|0x0162|0x0163|0x0164)"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x078b"; + match "product" "0x1234"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x079b"; + match "product" "(0x0027|0x004a|0x0062)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07a6"; + match "product" "(0x07c2|0x0986|0x8511|0x8513|0x8515)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "(0x0001|0x0004|0x000d|0x0017|0x002a|0x002d|0x002e|0x002f|0x003c|0x003f|0x0041|0x0042|0x9601)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0x110c|0x200c|0x2770|0x2870|0x3070|0x3071|0x3072|0x4000|0x4002|0x4003|0x4004|0x4007|0x400b|0x400c|0x4102|0x4104|0x420a|0x6001|0xabc1|0xb21b|0xb21c|0xb21d|0xb21e|0xb21f)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07c9"; + match "product" "0xb100"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07cf"; + match "product" "(0x2001|0x2002|0x2003)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07d1"; + match "product" "(0x3a0c|0x3c03|0x3c04|0x3c06|0x3c07|0x3c09|0x3c0a|0x3c0b|0x3c0d|0x3c0e|0x3c0f|0x3c11|0x3c13|0x3c15|0x3c16)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x081e"; + match "product" "0xdf00"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x082d"; + match "product" "(0x0100|0x0200|0x0300)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0830"; + match "product" "(0x0001|0x0002|0x0003|0x0020|0x0031|0x0040|0x0050|0x0060|0x0061|0x0070)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0833"; + match "product" "(0x012e|0x039f)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "(0x1046|0x4506|0x4506|0x4508|0x4521|0x5046|0x6618|0x7511|0x7512|0x7522|0x8522|0xa512|0xa618|0xa701|0xa702|0xb522|0xc522|0xd522|0xe501)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0841"; + match "product" "0x0001"; + action "kldload urio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "(0x1001|0x1002|0x1020|0x1040|0x4240|0x4260|0x4300|0x6100|0x6a00)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0856"; + match "product" "0xac01"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x085a"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x086e"; + match "product" "0x1920"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x087d"; + match "product" "0x5704"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08d1"; + match "product" "(0x0001|0x0003)"; + action "kldload if_cue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08dd"; + match "product" "(0x0986|0x0987|0x0988|0x8511|0x90ff)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08e6"; + match "product" "0x5501"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08fd"; + match "product" "0x000a"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0915"; + match "product" "(0x2000|0x2002)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x091e"; + match "product" "0x0004"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0921"; + match "product" "0x1001"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0930"; + match "product" "(0x0700|0x0705|0x0706|0x0707|0x0708|0x0709|0x070a|0x070b|0x0a07|0x0d45|0x1302)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x093c"; + match "product" "(0x0601|0x0701)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x094b"; + match "product" "0x0001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0951"; + match "product" "(0x0008|0x000a)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x095a"; + match "product" "0x3003"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0960"; + match "product" "(0x0065|0x0066|0x0067)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0961"; + match "product" "0x0010"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x099e"; + match "product" "(0x0052|0x4000)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x09aa"; + match "product" "0x1000"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x09d7"; + match "product" "0x0100"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0a46"; + match "product" "(0x0268|0x8515|0x9601)"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0a5c"; + match "product" "0x2033"; + action "kldload ubtbcmfw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0ace"; + match "product" "(0x1211|0x1215)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x5000|0x6000|0x6050|0x6100|0x6150|0x6200|0x6250|0x6300|0x6350|0x6500|0x6501|0x6600|0x6601|0x6701|0x6721|0x6741|0x6761|0x6800|0x6901|0x6911|0x6971|0x6971|0x7001|0x7011|0x7021|0x7041|0x7061|0x7100|0x7201|0x7211|0x7251|0x7301|0x7361|0x7381|0x7401|0x7501|0x7601|0x7601|0xc031|0xd013|0xd031|0xd033|0xd033|0xd055|0xd055)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x1706|0x1707|0x170c|0x171b|0x171d|0x1723|0x1724|0x1731|0x1732|0x1742|0x1760|0x1761|0x1784|0x1790|0x4200|0x4201|0x4202|0x420f|0x9200|0x9202)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b39"; + match "product" "(0x0109|0x0421)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b3b"; + match "product" "(0x1630|0x5630|0x6630)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b41"; + match "product" "0x0011"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b63"; + match "product" "0x6530"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b8c"; + match "product" "0x2303"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b95"; + match "product" "(0x1720|0x1780|0x7720|0x772a)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0baf"; + match "product" "(0x0118|0x0121)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bb2"; + match "product" "0x6098"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bb4"; + match "product" "(0x00ce|0x00cf|0x00cf|0x0a01|0x0a02|0x0a03|0x0a04|0x0a05|0x0a06|0x0a07|0x0a08|0x0a09|0x0a0a|0x0a0b|0x0a0c|0x0a0d|0x0a0e|0x0a0f|0x0a10|0x0a11|0x0a12|0x0a13|0x0a14|0x0a15|0x0a16|0x0a17|0x0a18|0x0a19|0x0a1a|0x0a1b|0x0a1c|0x0a1d|0x0a1e|0x0a1f|0x0a20|0x0a21|0x0a22|0x0a23|0x0a24|0x0a25|0x0a26|0x0a27|0x0a28|0x0a29|0x0a2a|0x0a2b|0x0a2c|0x0a2d|0x0a2e|0x0a2f|0x0a30|0x0a31|0x0a32|0x0a33|0x0a34|0x0a35|0x0a36|0x0a37|0x0a38|0x0a39|0x0a3a|0x0a3b|0x0a3c|0x0a3d|0x0a3e|0x0a3f|0x0a40|0x0a41|0x0a42|0x0a43|0x0a44|0x0a45|0x0a46|0x0a47|0x0a48|0x0a49|0x0a4a|0x0a4b|0x0a4c|0x0a4d|0x0a4e|0x0a4f|0x0a50|0x0a51|0x0a52|0x0a53|0x0a54|0x0a55|0x0a56|0x0a57|0x0a58|0x0a59|0x0a5a|0x0a5b|0x0a5c|0x0a5d|0x0a5e|0x0a5f|0x0a60|0x0a61|0x0a62|0x0a63|0x0a64|0x0a65|0x0a66|0x0a67|0x0a68|0x0a69|0x0a6a|0x0a6b|0x0a6c|0x0a6d|0x0a6e|0x0a6f|0x0a70|0x0a71|0x0a72|0x0a73|0x0a74|0x0a75|0x0a76|0x0a77|0x0a78|0x0a79|0x0a7a|0x0a7b|0x0a7c|0x0a7d|0x0a7e|0x0a7f|0x0a80|0x0a81|0x0a82|0x0a83|0x0a84|0x0a85|0x0a86|0x0a87|0x0a88|0x0a89|0x0a8a|0x0a8b|0x0a8c|0x0a8d|0x0a8e|0x0a8f|0x0a90|0x0a91|0x0a92|0x0a93|0x0a94|0x0a95|0x0a96|0x0a97|0x0a98|0x0a99|0x0a9a|0x0a9b|0x0a9c|0x0a9d|0x0a9e|0x0a9f|0x0bce)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bda"; + match "product" "(0x8150|0x8187|0x8189|0x8197|0x8198)"; + action "kldload if_rue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bed"; + match "product" "(0x1100|0x1101)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bf8"; + match "product" "(0x1001|0x1009)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c44"; + match "product" "0x03a2"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c88"; + match "product" "(0x17da|0x17da|0x180a)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c8e"; + match "product" "0x6000"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cad"; + match "product" "0x9001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "(0x0008|0x0011|0x0012|0x0015|0x001a|0x0022|0x0025)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cf3"; + match "product" "(0x0001|0x0003|0x0005)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0d8e"; + match "product" "(0x3762|0x7801|0x7811)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x3820|0x3821|0x3822|0x3870|0x3871|0x6861|0x6865|0x6869|0x6874|0x6877|0x6899|0x821a|0x822a|0x870a|0x871a|0x899a|0xa861|0xa874)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db7"; + match "product" "0x0002"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "(0x000d|0x0017|0x0021|0x0028|0x002b|0x002c|0x002d|0x0039|0x003b|0x003c|0x003d|0x003e|0x003f|0x0040|0x0041|0x0042|0x0047|0x0048|0x004a|0x004d|0x061c|0x9071|0x9075|0x90ac|0x9712)"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df7"; + match "product" "0x0620"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e0b"; + match "product" "(0x9031|0x9041)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e55"; + match "product" "0x110b"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e66"; + match "product" "(0x0001|0x0003|0x0009|0x000b|0x400c)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e67"; + match "product" "0x0002"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e7e"; + match "product" "0x1001"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0ea0"; + match "product" "0x6858"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eab"; + match "product" "0xc893"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eb0"; + match "product" "(0x9020|0x9021)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eba"; + match "product" "(0x1080|0x2080)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f3d"; + match "product" "(0x0112|0x0112)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f4e"; + match "product" "0x0200"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f88"; + match "product" "(0x3012|0x3014)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f94"; + match "product" "0x0001"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f98"; + match "product" "0x0201"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fb8"; + match "product" "(0x3001|0x3002|0x3003|0x4001)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fcf"; + match "product" "(0x1003|0x1004|0x1006)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fe6"; + match "product" "(0x8101|0x9700)"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x100d"; + match "product" "(0x9031|0x9032)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1011"; + match "product" "0x3198"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "(0x8001|0x8002|0x8007|0x8008|0x800a|0x800b|0x800c|0x800d)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1066"; + match "product" "(0x00ce|0x0300|0x0500|0x0600|0x0700)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x106c"; + match "product" "0x3701"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10a6"; + match "product" "0xaa26"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10ab"; + match "product" "0x10c5"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10b5"; + match "product" "(0xac70|0xac70)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10bd"; + match "product" "0x1427"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c4"; + match "product" "(0x0f91|0x1101|0x1601|0x800a|0x803b|0x8043|0x8044|0x8053|0x8066|0x806f|0x807a|0x80ca|0x80dd|0x80ed|0x80f6|0x8115|0x813d|0x813f|0x814a|0x814a|0x814b|0x8156|0x815e|0x818b|0x819f|0x81a6|0x81ac|0x81ad|0x81c8|0x81e2|0x81e7|0x81e8|0x81f2|0x8218|0x822b|0x826b|0x8293|0x82f9|0x8341|0x8382|0x83a8|0x8411|0x846e|0x8477|0xea60|0xea61|0xea71|0xf001|0xf002|0xf003|0xf004)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c5"; + match "product" "0xea61"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10ce"; + match "product" "0xea61"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1114"; + match "product" "(0x0001|0x0004|0x0006)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x114b"; + match "product" "(0x0110|0x0150)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1163"; + match "product" "0x0100"; + action "kldload ucycom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1182"; + match "product" "0x1388"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1186"; + match "product" "0x3e04"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1189"; + match "product" "0x0893"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1199"; + match "product" "(0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0112|0x0120|0x0218|0x0218|0x0220|0x0224|0x0fff|0x6802|0x6803|0x6804|0x6805|0x6808|0x6809|0x6812|0x6813|0x6815|0x6816|0x6820|0x6821|0x6822|0x6832|0x6833|0x6834|0x6835|0x6838|0x6839|0x683a|0x683b|0x683c|0x683d|0x683e|0x6850|0x6851|0x6852|0x6853|0x6855|0x6856|0x6859|0x685a|0x6880|0x6890|0x6891|0x6892|0x6893|0x68a3)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11ad"; + match "product" "0x0701"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11d9"; + match "product" "(0x1002|0x1003)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f5"; + match "product" "(0x0001|0x0003|0x0004|0x0005)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f6"; + match "product" "0x2001"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f7"; + match "product" "0x02df"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1231"; + match "product" "(0xce01|0xce02)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x126f"; + match "product" "0xa006"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x129b"; + match "product" "(0x1666|0x1828)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1465|0x14ac|0x1520)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12ef"; + match "product" "0x0100"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1342"; + match "product" "0x0204"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1371"; + match "product" "(0x9022|0x9032|0x9401)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1385"; + match "product" "(0x4250|0x5f00|0x5f02)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13ad"; + match "product" "0x9999"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "(0x000c|0x000d|0x0011|0x0018|0x001a|0x0020|0x0023|0x0024)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13d2"; + match "product" "0x0400"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13d3"; + match "product" "(0x3247|0x3262|0x3273|0x3284|0x3305)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1410"; + match "product" "(0x1100|0x1110|0x1120|0x1130|0x1400|0x1410|0x1420|0x1430|0x1450|0x2100|0x2110|0x2120|0x2130|0x2400|0x2410|0x2420|0x4100|0x4400|0x5010|0x5100|0x6000|0x6002|0x7042)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1416"; + match "product" "0x1110"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1435"; + match "product" "(0x0427|0x0711|0x0826|0x082a)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1453"; + match "product" "0x4026"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1472"; + match "product" "0x0009"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1482"; + match "product" "0x3c09"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1485"; + match "product" "(0x0001|0x0002)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "(0x1706|0x2070|0x2570|0x2573|0x2671|0x2770|0x2870|0x3070|0x3071|0x3072|0x3370|0x3572|0x8070|0x9020|0x9021)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "(0x3c02|0x3c06|0x3c07|0x3c08|0x3c09|0x3c11|0x3c12|0x3c22|0x3c23|0x3c25|0x3c25|0x3c27|0x3c28)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14ea"; + match "product" "(0xab10|0xab11|0xab13)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1555"; + match "product" "0x0004"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1557"; + match "product" "(0x7720|0x8150)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "(0x3006|0x300a|0x300b|0x300d|0x300e|0x3204|0x3205)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1582"; + match "product" "0x6003"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15a9"; + match "product" "(0x0004|0x0006|0x0010)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15c5"; + match "product" "0x0008"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15e8"; + match "product" "(0x9100|0x9110)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1614"; + match "product" "(0x0800|0x0802|0x7002)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1631"; + match "product" "(0x6200|0xc019)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1645"; + match "product" "(0x0005|0x0008|0x8005)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x166a"; + match "product" "0x0303"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x167b"; + match "product" "0x4001"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x168c"; + match "product" "0x0001"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "(0x0601|0x0710|0x0712|0x0722|0x0740|0x0744)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16ab"; + match "product" "(0x7801|0x7811)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "(0x6202|0x6501|0x6501|0x6502|0x6502)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d6"; + match "product" "(0x0001|0x0001)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d8"; + match "product" "(0x6006|0x6280|0x6280)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16dc"; + match "product" "(0x0010|0x0011|0x0012|0x0015)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1726"; + match "product" "(0x1000|0x1000)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "(0x0039|0x0070|0x0071|0x0073|0x0077|0x0078|0x0079)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1740"; + match "product" "(0x0605|0x0615|0x2000|0x9701|0x9702|0x9703|0x9705|0x9706|0x9707|0x9708|0x9709|0x9801)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1761"; + match "product" "0x0b05"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x177f"; + match "product" "(0x0153|0x0302|0x0313)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x17f4"; + match "product" "0xaaaa"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1843"; + match "product" "0x0200"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18c5"; + match "product" "(0x0002|0x0008|0x0012)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "(0x6196|0x6229|0x6232|0x6238|0x6259)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18ef"; + match "product" "0xe00f"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x19d2"; + match "product" "(0x0001|0x0002|0x0003|0x0004|0x0005|0x0006|0x0007|0x0008|0x0009|0x000a|0x000b|0x000c|0x000d|0x000e|0x000f|0x0010|0x0011|0x0012|0x0013|0x0014|0x0015|0x0016|0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0030|0x0031|0x0032|0x0033|0x0037|0x0039|0x0042|0x0043|0x0048|0x0049|0x0051|0x0052|0x0053|0x0054|0x0055|0x0057|0x0058|0x0059|0x0060|0x0061|0x0062|0x0063|0x0064|0x0066|0x0069|0x0070|0x0073|0x0076|0x0078|0x0082|0x0086|0x0117|0x2000|0x2002|0x2003|0xfff1|0xfff5|0xfffe)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1a86"; + match "product" "0x7523"; + action "kldload uchcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1a8d"; + match "product" "(0x1002|0x1003|0x1004|0x1005|0x1006|0x1007|0x1008|0x1009|0x100a|0x100b|0x100c|0x100d|0x100e|0x100f|0x1010|0x1011|0x1012)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b3d"; + match "product" "0x0153"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b75"; + match "product" "(0x3072|0x8187)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1bbb"; + match "product" "(0x0000|0xf000)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1bc7"; + match "product" "(0x1003|0x1004)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1be3"; + match "product" "0x07a6"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1c9e"; + match "product" "(0x6061|0x9603|0xf000)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1cf1"; + match "product" "(0x0001|0x0004)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1d09"; + match "product" "0x4000"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1d4d"; + match "product" "(0x0002|0x000c|0x000e|0x0010)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1da5"; + match "product" "(0x4512|0x4515|0x4519|0x4523)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1e0e"; + match "product" "(0x9000|0x9200|0xce16)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1eda"; + match "product" "0x2310"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "(0x1a00|0x200c|0x3a00|0x3a02|0x3a04|0x3c00|0x3c05|0x3c09|0x3c0a|0x4000|0x4001|0x4002|0x4003|0x400b|0x4102|0xabc1)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "(0x5303|0xab01|0xab24|0xab25|0xab50|0xc007|0xed01|0xed02|0xed06|0xed14)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x203d"; + match "product" "(0x1480|0x14a1|0x14a9)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20b8"; + match "product" "0x8888"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20b9"; + match "product" "0x1682"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x22b8"; + match "product" "(0x4204|0x4214|0x4224|0x4234|0x4244|0x600c|0x6027)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2478"; + match "product" "0x2008"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3334"; + match "product" "0x1701"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3340"; + match "product" "(0x011c|0x0326|0x0426|0x043a|0x051c|0x053a|0x071c|0x0b1c|0x0e3a|0x0f1c|0x0f3a|0x1326|0x191c|0x2326|0x3326)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3708"; + match "product" "(0x20ce|0x21ce)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4113"; + match "product" "(0x0210|0x0211|0x0400|0x0410)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "(0x4001|0x4002|0x4003|0x4004|0x4005|0x4006|0x4007|0x4008|0x4009|0x8102|0x8104|0x8114|0x8115|0x8116|0x8117|0x8118|0x8128|0x8129|0x8133|0x8134|0x8135|0x8136|0x8137|0x8138|0x8180|0x8181|0x8182|0x9500)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4348"; + match "product" "0x5523"; + action "kldload uchcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4505"; + match "product" "0x0010"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4766"; + match "product" "0x0001"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5173"; + match "product" "0x1809"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5372"; + match "product" "0x2303"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5a57"; + match "product" "(0x0260|0x0280|0x0282|0x0283|0x0284|0x5257)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5e04"; + match "product" "0xce00"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6189"; + match "product" "(0x182d|0x2068)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6547"; + match "product" "0x0232"; + action "kldload uark"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6891"; + match "product" "0xa727"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x7392"; + match "product" "(0x7318|0x7711|0x7717|0x7718)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x8516"; + match "product" "(0x2070|0x2770|0x2870|0x3070|0x3071|0x3072|0x3572)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "(0x7703|0x7730|0x7820|0x7830|0x7840)"; + action "kldload umoscom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9e88"; + match "product" "0x9e8f"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0xdaae"; + match "product" "0xead6"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x02"; + match "intprotocol" "0x01"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x02"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x03"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0xe0"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ng_ubt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0xff"; + match "intsubclass" "0x5d"; + match "intprotocol" "0x01"; + action "kldload uhid"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x01"; + match "intsubclass" "0x01"; + action "kldload snd_uaudio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x01"; + match "intsubclass" "0x03"; + action "kldload snd_uaudio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x88"; + action "kldload ufoma"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + action "kldload uhid"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x08"; + action "kldload umass"; +}; + +# 1626 usb_host entries processed + -- cgit v1.1 From 960e1ff18c7cb3dcf4b5df7ce4af59f81edcfc80 Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 24 Jun 2011 21:39:38 +0000 Subject: Split out host_pcib_get_busno() from the generic PCI-PCI bridge driver to start a new file that will hold utility APIs used by various Host-PCI bridge drivers and drivers that provide PCI domains. --- sys/conf/files | 1 + sys/dev/pci/pci_pci.c | 92 ---------------------------------- sys/dev/pci/pci_subr.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 92 deletions(-) create mode 100644 sys/dev/pci/pci_subr.c diff --git a/sys/conf/files b/sys/conf/files index 1a8d5ff..26c5923 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1552,6 +1552,7 @@ dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_pci.c optional pci +dev/pci/pci_subr.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pci/vga_pci.c optional pci diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c index da8465c..93bbf3a 100644 --- a/sys/dev/pci/pci_pci.c +++ b/sys/dev/pci/pci_pci.c @@ -38,16 +38,12 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include #include #include -#include -#include - #include #include #include @@ -1432,91 +1428,3 @@ pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate) bus = device_get_parent(pcib); return (PCIB_POWER_FOR_SLEEP(bus, dev, pstate)); } - -/* - * Try to read the bus number of a host-PCI bridge using appropriate config - * registers. - */ -int -host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, - uint8_t *busnum) -{ - uint32_t id; - - id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); - if (id == 0xffffffff) - return (0); - - switch (id) { - case 0x12258086: - /* Intel 824?? */ - /* XXX This is a guess */ - /* *busnum = read_config(bus, slot, func, 0x41, 1); */ - *busnum = bus; - break; - case 0x84c48086: - /* Intel 82454KX/GX (Orion) */ - *busnum = read_config(bus, slot, func, 0x4a, 1); - break; - case 0x84ca8086: - /* - * For the 450nx chipset, there is a whole bundle of - * things pretending to be host bridges. The MIOC will - * be seen first and isn't really a pci bridge (the - * actual busses are attached to the PXB's). We need to - * read the registers of the MIOC to figure out the - * bus numbers for the PXB channels. - * - * Since the MIOC doesn't have a pci bus attached, we - * pretend it wasn't there. - */ - return (0); - case 0x84cb8086: - switch (slot) { - case 0x12: - /* Intel 82454NX PXB#0, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd0, 1); - break; - case 0x13: - /* Intel 82454NX PXB#0, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; - break; - case 0x14: - /* Intel 82454NX PXB#1, Bus#A */ - *busnum = read_config(bus, 0x10, func, 0xd3, 1); - break; - case 0x15: - /* Intel 82454NX PXB#1, Bus#B */ - *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; - break; - } - break; - - /* ServerWorks -- vendor 0x1166 */ - case 0x00051166: - case 0x00061166: - case 0x00081166: - case 0x00091166: - case 0x00101166: - case 0x00111166: - case 0x00171166: - case 0x01011166: - case 0x010f1014: - case 0x01101166: - case 0x02011166: - case 0x02251166: - case 0x03021014: - *busnum = read_config(bus, slot, func, 0x44, 1); - break; - - /* Compaq/HP -- vendor 0x0e11 */ - case 0x60100e11: - *busnum = read_config(bus, slot, func, 0xc8, 1); - break; - default: - /* Don't know how to read bus number. */ - return 0; - } - - return 1; -} diff --git a/sys/dev/pci/pci_subr.c b/sys/dev/pci/pci_subr.c new file mode 100644 index 0000000..7f0c806 --- /dev/null +++ b/sys/dev/pci/pci_subr.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2011 Advanced Computing Technologies LLC + * Written by: John H. Baldwin + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Support APIs for Host to PCI bridge drivers and drivers that + * provide PCI domains. + */ + +#include +#include +#include + +#include +#include +#include + +/* + * Try to read the bus number of a host-PCI bridge using appropriate config + * registers. + */ +int +host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func, + uint8_t *busnum) +{ + uint32_t id; + + id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4); + if (id == 0xffffffff) + return (0); + + switch (id) { + case 0x12258086: + /* Intel 824?? */ + /* XXX This is a guess */ + /* *busnum = read_config(bus, slot, func, 0x41, 1); */ + *busnum = bus; + break; + case 0x84c48086: + /* Intel 82454KX/GX (Orion) */ + *busnum = read_config(bus, slot, func, 0x4a, 1); + break; + case 0x84ca8086: + /* + * For the 450nx chipset, there is a whole bundle of + * things pretending to be host bridges. The MIOC will + * be seen first and isn't really a pci bridge (the + * actual busses are attached to the PXB's). We need to + * read the registers of the MIOC to figure out the + * bus numbers for the PXB channels. + * + * Since the MIOC doesn't have a pci bus attached, we + * pretend it wasn't there. + */ + return (0); + case 0x84cb8086: + switch (slot) { + case 0x12: + /* Intel 82454NX PXB#0, Bus#A */ + *busnum = read_config(bus, 0x10, func, 0xd0, 1); + break; + case 0x13: + /* Intel 82454NX PXB#0, Bus#B */ + *busnum = read_config(bus, 0x10, func, 0xd1, 1) + 1; + break; + case 0x14: + /* Intel 82454NX PXB#1, Bus#A */ + *busnum = read_config(bus, 0x10, func, 0xd3, 1); + break; + case 0x15: + /* Intel 82454NX PXB#1, Bus#B */ + *busnum = read_config(bus, 0x10, func, 0xd4, 1) + 1; + break; + } + break; + + /* ServerWorks -- vendor 0x1166 */ + case 0x00051166: + case 0x00061166: + case 0x00081166: + case 0x00091166: + case 0x00101166: + case 0x00111166: + case 0x00171166: + case 0x01011166: + case 0x010f1014: + case 0x01101166: + case 0x02011166: + case 0x02251166: + case 0x03021014: + *busnum = read_config(bus, slot, func, 0x44, 1); + break; + + /* Compaq/HP -- vendor 0x0e11 */ + case 0x60100e11: + *busnum = read_config(bus, slot, func, 0xc8, 1); + break; + default: + /* Don't know how to read bus number. */ + return 0; + } + + return 1; +} -- cgit v1.1 From 97be6feacb7ff2fabc0576a8d100d3c75e5e7645 Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 24 Jun 2011 22:01:56 +0000 Subject: - Export more USB device ID's. - Update bus_auto.conf accordingly. MFC after: 3 days --- etc/devd/bus_auto.conf | 36 +++++++++++++++++++++++++++++++++++- sys/dev/usb/input/uep.c | 21 +++++++++++---------- sys/dev/usb/input/ukbd.c | 7 +++++++ sys/dev/usb/input/ums.c | 7 +++++++ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/etc/devd/bus_auto.conf b/etc/devd/bus_auto.conf index 596fa7e..a1c7236 100644 --- a/etc/devd/bus_auto.conf +++ b/etc/devd/bus_auto.conf @@ -86,6 +86,14 @@ nomatch 32 { nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; + match "vendor" "0x0123"; + match "product" "0x0001"; + action "kldload uep"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; match "vendor" "0x03e8"; match "product" "0x0008"; action "kldload if_kue"; @@ -1254,6 +1262,14 @@ nomatch 32 { nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; + match "vendor" "0x0eef"; + match "product" "(0x0001|0x0002)"; + action "kldload uep"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; match "vendor" "0x0f3d"; match "product" "(0x0112|0x0112)"; action "kldload u3g"; @@ -2263,6 +2279,24 @@ nomatch 32 { nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; + match "intclass" "0x03"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ukbd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + match "intsubclass" "0x01"; + match "intprotocol" "0x02"; + action "kldload ums"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; match "intclass" "0x07"; match "intsubclass" "0x01"; match "intprotocol" "0x01"; @@ -2343,5 +2377,5 @@ nomatch 32 { action "kldload umass"; }; -# 1626 usb_host entries processed +# 1631 usb_host entries processed diff --git a/sys/dev/usb/input/uep.c b/sys/dev/usb/input/uep.c index 048452d..e90298b 100644 --- a/sys/dev/usb/input/uep.c +++ b/sys/dev/usb/input/uep.c @@ -288,6 +288,12 @@ static const struct usb_config uep_config[UEP_N_TRANSFER] = { }, }; +static const STRUCT_USB_HOST_ID uep_devs[] = { + {USB_VPI(USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL, 0)}, + {USB_VPI(USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL2, 0)}, + {USB_VPI(USB_VENDOR_EGALAX2, USB_PRODUCT_EGALAX2_TPANEL, 0)}, +}; + static int uep_probe(device_t dev) { @@ -295,17 +301,12 @@ uep_probe(device_t dev) if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); + if (uaa->info.bConfigIndex != 0) + return (ENXIO); + if (uaa->info.bIfaceIndex != 0) + return (ENXIO); - if ((uaa->info.idVendor == USB_VENDOR_EGALAX) && - ((uaa->info.idProduct == USB_PRODUCT_EGALAX_TPANEL) || - (uaa->info.idProduct == USB_PRODUCT_EGALAX_TPANEL2))) - return (BUS_PROBE_SPECIFIC); - - if ((uaa->info.idVendor == USB_VENDOR_EGALAX2) && - (uaa->info.idProduct == USB_PRODUCT_EGALAX2_TPANEL)) - return (BUS_PROBE_SPECIFIC); - - return (ENXIO); + return (usbd_lookup_id_by_uaa(uep_devs, sizeof(uep_devs), uaa)); } static int diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 9182663..b03f884 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -745,6 +745,13 @@ static const struct usb_config ukbd_config[UKBD_N_TRANSFER] = { }, }; +/* A match on these entries will load ukbd */ +static const STRUCT_USB_HOST_ID __used ukbd_devs[] = { + {USB_IFACE_CLASS(UICLASS_HID), + USB_IFACE_SUBCLASS(UISUBCLASS_BOOT), + USB_IFACE_PROTOCOL(UIPROTO_BOOT_KEYBOARD),}, +}; + static int ukbd_probe(device_t dev) { diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c index af9aa1f..3c4f36e 100644 --- a/sys/dev/usb/input/ums.c +++ b/sys/dev/usb/input/ums.c @@ -355,6 +355,13 @@ static const struct usb_config ums_config[UMS_N_TRANSFER] = { }, }; +/* A match on these entries will load ums */ +static const STRUCT_USB_HOST_ID __used ums_devs[] = { + {USB_IFACE_CLASS(UICLASS_HID), + USB_IFACE_SUBCLASS(UISUBCLASS_BOOT), + USB_IFACE_PROTOCOL(UIPROTO_MOUSE),}, +}; + static int ums_probe(device_t dev) { -- cgit v1.1 From 76e2eec6e1b5cd6ff5d24d6629a89ad35414c6c2 Mon Sep 17 00:00:00 2001 From: jilles Date: Fri, 24 Jun 2011 22:08:26 +0000 Subject: sh(1): Improve documentation of shell patterns: * Shell patterns are also for ${var#pat} and the like. * An '!' by itself will not trigger pathname generation so do not call it a meta-character, even though it has a special meaning directly after an '['. * Character ranges are locale-dependent. * A '^' will complement a character class like '!' but is non-standard. MFC after: 1 week --- bin/sh/sh.1 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index bb101336..4a9fe06 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -1629,15 +1629,15 @@ There are two restrictions on this: first, a pattern cannot match a string containing a slash, and second, a pattern cannot match a string starting with a period unless the first character of the pattern is a period. -The next section describes the patterns used for both -Pathname Expansion and the +The next section describes the patterns used for +Pathname Expansion, +the four varieties of parameter expansion for substring processing and the .Ic case command. .Ss Shell Patterns A pattern consists of normal characters, which match themselves, and meta-characters. The meta-characters are -.Ql \&! , .Ql * , .Ql \&? , and @@ -1667,7 +1667,7 @@ matches a .Ql \&[ rather than introducing a character class. A character class matches any of the characters between the square brackets. -A range of characters may be specified using a minus sign. +A locale-dependent range of characters may be specified using a minus sign. A named class of characters (see .Xr wctype 3 ) may be specified by surrounding the name with @@ -1680,12 +1680,17 @@ is a shell pattern that matches a single letter. The character class may be complemented by making an exclamation point .Pq Ql !\& the first character of the character class. +A caret +.Pq Ql ^ +has the same effect but is non-standard. .Pp To include a .Ql \&] in a character class, make it the first character listed (after the -.Ql \&! , +.Ql \&! +or +.Ql ^ , if any). To include a .Ql - , -- cgit v1.1 From bad755fcf90ffd8e4e49c67d3c08b56e4f038838 Mon Sep 17 00:00:00 2001 From: cognet Date: Fri, 24 Jun 2011 23:26:45 +0000 Subject: Comment out AH_DEBUG, to get this kernel to compile, until AH_DEBUG is fixed. --- sys/arm/conf/CAMBRIA | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/arm/conf/CAMBRIA b/sys/arm/conf/CAMBRIA index 6862129..befe28a 100644 --- a/sys/arm/conf/CAMBRIA +++ b/sys/arm/conf/CAMBRIA @@ -130,7 +130,7 @@ options ATH_DIAGAPI #options ATH_TX99_DIAG device ath_rate_sample # SampleRate tx rate control for ath -options AH_DEBUG +#options AH_DEBUG #options AH_ASSERT options AH_PRIVATE_DIAG #device ath_ar5210 -- cgit v1.1 From 3dd67494c4b789dea623cc58dc5409eac05523c1 Mon Sep 17 00:00:00 2001 From: adrian Date: Fri, 24 Jun 2011 23:59:14 +0000 Subject: Small fix to bring the non-debug definitions of HALDEBUG/HALDEBUG_G in line with the debug definitions. --- sys/dev/ath/ath_hal/ah_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h index 2bb163f..120620c 100644 --- a/sys/dev/ath/ath_hal/ah_internal.h +++ b/sys/dev/ath/ath_hal/ah_internal.h @@ -528,8 +528,8 @@ extern int ath_hal_debug; /* Global debug flags */ extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) __printflike(3,4); #else -#define HALDEBUG(_ah, __m, _fmt, ...) -#define HALDEBUG_G(_ah, __m, _fmt, ...) +#define HALDEBUG(_ah, __m, ...) +#define HALDEBUG_G(_ah, __m, ...) #endif /* AH_DEBUG */ /* -- cgit v1.1 From 19f236ce5f33a01e1f16ef7d7160d9e43a1a5d54 Mon Sep 17 00:00:00 2001 From: adrian Date: Sat, 25 Jun 2011 00:34:40 +0000 Subject: Commit missing piece from a couple days ago - re-add ath_hal_debug. --- sys/dev/ath/ah_osdep.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c index c0f9b8c..cfcfc4a 100644 --- a/sys/dev/ath/ah_osdep.c +++ b/sys/dev/ath/ah_osdep.c @@ -76,6 +76,14 @@ extern void DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...); /* NB: put this here instead of the driver to avoid circular references */ SYSCTL_NODE(_hw, OID_AUTO, ath, CTLFLAG_RD, 0, "Atheros driver parameters"); +SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, "Atheros HAL parameters"); + +#ifdef AH_DEBUG +int ath_hal_debug = 0; +SYSCTL_INT(_hw_ath_hal, OID_AUTO, debug, CTLFLAG_RW, &ath_hal_debug, + 0, "Atheros HAL debugging printfs"); +TUNABLE_INT("hw.ath.hal.debug", &ath_hal_debug); +#endif /* AH_DEBUG */ MALLOC_DEFINE(M_ATH_HAL, "ath_hal", "ath hal data"); @@ -147,8 +155,6 @@ DO_HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...) #include #include -SYSCTL_NODE(_hw_ath, OID_AUTO, hal, CTLFLAG_RD, 0, "Atheros HAL parameters"); - static struct alq *ath_hal_alq; static int ath_hal_alq_emitdev; /* need to emit DEVICE record */ static u_int ath_hal_alq_lost; /* count of lost records */ -- cgit v1.1 From 215e258fd1019b3c027d1ca12d509337760ac8cf Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 25 Jun 2011 02:15:14 +0000 Subject: Switch to the event timers infrastructure. This includes: o Setting td_intr_frame to the XIVs trap frame because it's referenced by the ET event handler. o Signal EOI to the CPU before calling the registered XIV handlers. This prevents lost ITC interrupts, which cause starvation in one-shot mode. o Adding support for IPI_HARDCLOCK with corresponding per-CPU counters. o Have the APs call cpu_initclocks() so as to limited the scattering of clock related initialization. cpu_initclocks() calls the _bsp() or _ap() version accordingly. o Uncomment the ET clock handling in cpu_idle(). o Update the DDB 'show pcpu' output for the new MD fields. o Entirely rewritten ia64_ih_clock(). Note that we don't create as many clock XIVs as we have CPUs, as is done on PowerPC. It doesn't scale. We can only have 240 XIVs and we can have more CPUs than that. There's a single intrcnt index for the cumulative clock ticks and we keep per CPU counts in the PCPU stats structure. o Register the ITC by hooking SI_SUB_CONFIGURE (2nd order). Open issues: o Clock interrupts can still be lost. Some tweaking is still necessary. Thanks to: mav@ for his support, feedback and explanations. ET stats while committing: eris% sysctl machdep.cpu | grep nclks machdep.cpu.0.nclks: 24007 machdep.cpu.1.nclks: 22895 machdep.cpu.2.nclks: 13523 machdep.cpu.3.nclks: 9342 machdep.cpu.4.nclks: 9103 machdep.cpu.5.nclks: 9298 machdep.cpu.6.nclks: 10039 machdep.cpu.7.nclks: 9479 eris% vmstat -i | grep clock clock 108599 50 --- sys/conf/files.ia64 | 1 + sys/ia64/ia64/clock.c | 189 +++++++++++++++++++++++---------------------- sys/ia64/ia64/db_machdep.c | 12 +-- sys/ia64/ia64/interrupt.c | 8 +- sys/ia64/ia64/machdep.c | 9 ++- sys/ia64/ia64/mp_machdep.c | 18 ++++- sys/ia64/include/pcpu.h | 4 +- sys/ia64/include/smp.h | 2 + 8 files changed, 137 insertions(+), 106 deletions(-) diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64 index 15ef939..e341230 100644 --- a/sys/conf/files.ia64 +++ b/sys/conf/files.ia64 @@ -120,6 +120,7 @@ ia64/pci/pci_cfgreg.c optional pci isa/syscons_isa.c optional sc isa/vga_isa.c optional vga kern/imgact_elf32.c optional compat_freebsd32 +kern/kern_clocksource.c standard libkern/bcmp.c standard libkern/ffsl.c standard libkern/fls.c standard diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index 33dbb2e..5f0e2fe 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -32,9 +32,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include +#include #include #include @@ -45,26 +47,12 @@ __FBSDID("$FreeBSD$"); #include #include -SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics"); - -static int adjust_edges = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_edges, CTLFLAG_RD, - &adjust_edges, 0, "Number of times ITC got more than 12.5% behind"); - -static int adjust_excess = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_excess, CTLFLAG_RD, - &adjust_excess, 0, "Total number of ignored ITC interrupts"); - -static int adjust_lost = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_lost, CTLFLAG_RD, - &adjust_lost, 0, "Total number of lost ITC interrupts"); - -static int adjust_ticks = 0; -SYSCTL_INT(_debug_clock, OID_AUTO, adjust_ticks, CTLFLAG_RD, - &adjust_ticks, 0, "Total number of ITC interrupts with adjustment"); +#define CLOCK_ET_OFF 0 +#define CLOCK_ET_PERIODIC 1 +#define CLOCK_ET_ONESHOT 2 +static struct eventtimer ia64_clock_et; static u_int ia64_clock_xiv; -static uint64_t ia64_clock_reload; #ifndef SMP static timecounter_get_t ia64_get_timecount; @@ -87,75 +75,100 @@ ia64_get_timecount(struct timecounter* tc) static u_int ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf) { - uint64_t adj, clk, itc; - int64_t delta; - int count; + struct eventtimer *et; + uint64_t itc, load; + uint32_t mode; PCPU_INC(md.stats.pcs_nclks); + intrcnt[INTRCNT_CLOCK]++; - if (PCPU_GET(cpuid) == 0) { - /* - * Clock processing on the BSP. - */ - intrcnt[INTRCNT_CLOCK]++; + itc = ia64_get_itc(); + PCPU_SET(md.clock, itc); - itc = ia64_get_itc(); + mode = PCPU_GET(md.clock_mode); + if (mode == CLOCK_ET_PERIODIC) { + load = PCPU_GET(md.clock_load); + ia64_set_itm(itc + load); + } else + ia64_set_itv((1 << 16) | xiv); + ia64_srlz_d(); - adj = PCPU_GET(md.clockadj); - clk = PCPU_GET(md.clock); + et = &ia64_clock_et; + if (et->et_active) + et->et_event_cb(et, et->et_arg); + return (0); +} - delta = itc - clk; - count = 0; - while (delta >= ia64_clock_reload) { -#ifdef SMP - ipi_all_but_self(ia64_clock_xiv); -#endif - hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - if (profprocs != 0) - profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - statclock(TRAPF_USERMODE(tf)); - delta -= ia64_clock_reload; - clk += ia64_clock_reload; - if (adj != 0) - adjust_ticks++; - count++; - } - ia64_set_itm(ia64_get_itc() + ia64_clock_reload - adj); - ia64_srlz_d(); - if (count > 0) { - adjust_lost += count - 1; - if (delta > (ia64_clock_reload >> 3)) { - if (adj == 0) - adjust_edges++; - adj = ia64_clock_reload >> 4; - } else - adj = 0; - } else { - adj = 0; - adjust_excess++; - } - PCPU_SET(md.clock, clk); - PCPU_SET(md.clockadj, adj); +/* + * Event timer start method. + */ +static int +ia64_clock_start(struct eventtimer *et, struct bintime *first, + struct bintime *period) +{ + u_long itc, load; + register_t is; + + if (period != NULL) { + PCPU_SET(md.clock_mode, CLOCK_ET_PERIODIC); + load = (et->et_frequency * (period->frac >> 32)) >> 32; + if (period->sec > 0) + load += et->et_frequency * period->sec; } else { - /* - * Clock processing on the BSP. - */ - hardclock_cpu(TRAPF_USERMODE(tf)); - if (profprocs != 0) - profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - statclock(TRAPF_USERMODE(tf)); + PCPU_SET(md.clock_mode, CLOCK_ET_ONESHOT); + load = 0; } + PCPU_SET(md.clock_load, load); + + if (first != NULL) { + load = (et->et_frequency * (first->frac >> 32)) >> 32; + if (first->sec > 0) + load += et->et_frequency * first->sec; + } + + is = intr_disable(); + itc = ia64_get_itc(); + ia64_set_itm(itc + load); + ia64_set_itv(ia64_clock_xiv); + ia64_srlz_d(); + intr_restore(is); return (0); } /* - * Start the real-time and statistics clocks. We use ar.itc and cr.itm - * to implement a 1000hz clock. + * Event timer stop method. + */ +static int +ia64_clock_stop(struct eventtimer *et) +{ + + ia64_set_itv((1 << 16) | ia64_clock_xiv); + ia64_srlz_d(); + PCPU_SET(md.clock_mode, CLOCK_ET_OFF); + PCPU_SET(md.clock_load, 0); + return (0); +} + +/* + * We call cpu_initclocks() on the APs as well. It allows us to + * group common initialization in the same function. */ void cpu_initclocks() { + + ia64_clock_stop(NULL); + if (PCPU_GET(cpuid) == 0) + cpu_initclocks_bsp(); + else + cpu_initclocks_ap(); +} + +static void +clock_configure(void *dummy) +{ + struct eventtimer *et; u_long itc_freq; ia64_clock_xiv = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IPI, @@ -165,31 +178,23 @@ cpu_initclocks() itc_freq = (u_long)ia64_itc_freq() * 1000000ul; - stathz = hz; - ia64_clock_reload = (itc_freq + hz/2) / hz; + et = &ia64_clock_et; + et->et_name = "ITC"; + et->et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU; + et->et_quality = 1000; + et->et_frequency = itc_freq; + et->et_min_period.sec = 0; + et->et_min_period.frac = ((1ul << 32) / itc_freq) << 32; + et->et_max_period.sec = 0xfffffff0 / itc_freq; + et->et_max_period.frac = ((0xfffffffeul << 32) / itc_freq) << 32; + et->et_start = ia64_clock_start; + et->et_stop = ia64_clock_stop; + et->et_priv = NULL; + et_register(et); #ifndef SMP ia64_timecounter.tc_frequency = itc_freq; tc_init(&ia64_timecounter); #endif - - PCPU_SET(md.clockadj, 0); - PCPU_SET(md.clock, ia64_get_itc()); - ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload); - ia64_set_itv(ia64_clock_xiv); - ia64_srlz_d(); -} - -void -cpu_startprofclock(void) -{ - - /* nothing to do */ -} - -void -cpu_stopprofclock(void) -{ - - /* nothing to do */ } +SYSINIT(clkcfg, SI_SUB_CONFIGURE, SI_ORDER_SECOND, clock_configure, NULL); diff --git a/sys/ia64/ia64/db_machdep.c b/sys/ia64/ia64/db_machdep.c index 9d583a1..b689a3c 100644 --- a/sys/ia64/ia64/db_machdep.c +++ b/sys/ia64/ia64/db_machdep.c @@ -578,11 +578,13 @@ db_show_mdpcpu(struct pcpu *pc) { struct pcpu_md *md = &pc->pc_md; - db_printf("MD: vhpt = %#lx\n", md->vhpt); - db_printf("MD: lid = %#lx\n", md->lid); - db_printf("MD: clock = %#lx/%#lx\n", md->clock, md->clockadj); - db_printf("MD: stats = %p\n", &md->stats); - db_printf("MD: pmap = %p\n", md->current_pmap); + db_printf("MD: vhpt = %#lx\n", md->vhpt); + db_printf("MD: lid = %#lx\n", md->lid); + db_printf("MD: clock = %#lx\n", md->clock); + db_printf("MD: clock_mode = %u\n", md->clock_mode); + db_printf("MD: clock_load = %#lx\n", md->clock_load); + db_printf("MD: stats = %p\n", &md->stats); + db_printf("MD: pmap = %p\n", md->current_pmap); } void diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index adb16ec..f4e5594 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -309,6 +309,7 @@ void ia64_handle_intr(struct trapframe *tf) { struct thread *td; + struct trapframe *stf; u_int xiv; td = curthread; @@ -323,17 +324,20 @@ ia64_handle_intr(struct trapframe *tf) } critical_enter(); + stf = td->td_intr_frame; + td->td_intr_frame = tf; do { + ia64_set_eoi(0); + ia64_srlz_d(); CTR2(KTR_INTR, "INTR: ITC=%u, XIV=%u", (u_int)tf->tf_special.ifa, xiv); (ia64_handler[xiv])(td, xiv, tf); - ia64_set_eoi(0); - ia64_srlz_d(); xiv = ia64_get_ivr(); ia64_srlz_d(); } while (xiv != 15); + td->td_intr_frame = stf; critical_exit(); out: diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 185e13c..2bfd62e 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -347,6 +347,11 @@ cpu_startup(void *dummy) SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx, SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO, + "nhardclocks", CTLFLAG_RD, &pcs->pcs_nhardclocks, + "Number of IPI_HARDCLOCK interrupts"); + + SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx, + SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO, "nhighfps", CTLFLAG_RD, &pcs->pcs_nhighfps, "Number of IPI_HIGH_FP interrupts"); @@ -416,12 +421,10 @@ cpu_idle(int busy) { register_t ie; -#if 0 if (!busy) { critical_enter(); cpu_idleclock(); } -#endif ie = intr_disable(); KASSERT(ie != 0, ("%s called with interrupts disabled\n", __func__)); @@ -436,12 +439,10 @@ cpu_idle(int busy) ia64_enable_intr(); } -#if 0 if (!busy) { cpu_activeclock(); critical_exit(); } -#endif } int diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index 15afea0..59b14d0 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -77,6 +77,7 @@ void ia64_ap_startup(void); struct ia64_ap_state ia64_ap_state; int ia64_ipi_ast; +int ia64_ipi_hardclock; int ia64_ipi_highfp; int ia64_ipi_nmi; int ia64_ipi_preempt; @@ -108,6 +109,16 @@ ia64_ih_ast(struct thread *td, u_int xiv, struct trapframe *tf) } static u_int +ia64_ih_hardclock(struct thread *td, u_int xiv, struct trapframe *tf) +{ + + PCPU_INC(md.stats.pcs_nhardclocks); + CTR1(KTR_SMP, "IPI_HARDCLOCK, cpuid=%d", PCPU_GET(cpuid)); + hardclockintr(); + return (0); +} + +static u_int ia64_ih_highfp(struct thread *td, u_int xiv, struct trapframe *tf) { @@ -233,10 +244,11 @@ ia64_ap_startup(void) CTR1(KTR_SMP, "SMP: cpu%d launched", PCPU_GET(cpuid)); - /* Mask interval timer interrupts on APs. */ - ia64_set_itv(0x10000); + cpu_initclocks(); + ia64_set_tpr(0); ia64_srlz_d(); + ia64_enable_intr(); sched_throw(NULL); @@ -413,6 +425,8 @@ cpu_mp_unleash(void *dummy) /* Allocate XIVs for IPIs */ ia64_ipi_ast = ia64_xiv_alloc(PI_DULL, IA64_XIV_IPI, ia64_ih_ast); + ia64_ipi_hardclock = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IPI, + ia64_ih_hardclock); ia64_ipi_highfp = ia64_xiv_alloc(PI_AV, IA64_XIV_IPI, ia64_ih_highfp); ia64_ipi_preempt = ia64_xiv_alloc(PI_SOFT, IA64_XIV_IPI, ia64_ih_preempt); diff --git a/sys/ia64/include/pcpu.h b/sys/ia64/include/pcpu.h index 05e2cc1..5ad61ba 100644 --- a/sys/ia64/include/pcpu.h +++ b/sys/ia64/include/pcpu.h @@ -37,6 +37,7 @@ struct pcpu_stats { u_long pcs_nasts; /* IPI_AST counter. */ u_long pcs_nclks; /* Clock interrupt counter. */ u_long pcs_nextints; /* ExtINT counter. */ + u_long pcs_nhardclocks; /* IPI_HARDCLOCK counter. */ u_long pcs_nhighfps; /* IPI_HIGH_FP counter. */ u_long pcs_nhwints; /* Hardware int. counter. */ u_long pcs_npreempts; /* IPI_PREEMPT counter. */ @@ -51,7 +52,8 @@ struct pcpu_md { vm_offset_t vhpt; /* Address of VHPT */ uint64_t lid; /* local CPU ID */ uint64_t clock; /* Clock counter. */ - uint64_t clockadj; /* Clock adjust. */ + uint64_t clock_load; /* Clock reload value. */ + uint32_t clock_mode; /* Clock ET mode */ uint32_t awake:1; /* CPU is awake? */ struct pcpu_stats stats; /* Interrupt stats. */ #ifdef _KERNEL diff --git a/sys/ia64/include/smp.h b/sys/ia64/include/smp.h index d2aff76..b80d6a0 100644 --- a/sys/ia64/include/smp.h +++ b/sys/ia64/include/smp.h @@ -7,6 +7,7 @@ #ifdef _KERNEL #define IPI_AST ia64_ipi_ast +#define IPI_HARDCLOCK ia64_ipi_hardclock #define IPI_PREEMPT ia64_ipi_preempt #define IPI_RENDEZVOUS ia64_ipi_rndzvs #define IPI_STOP ia64_ipi_stop @@ -37,6 +38,7 @@ struct ia64_ap_state { }; extern int ia64_ipi_ast; +extern int ia64_ipi_hardclock; extern int ia64_ipi_highfp; extern int ia64_ipi_nmi; extern int ia64_ipi_preempt; -- cgit v1.1 From 882ae336b550700da43586e85b20c164ad564f8b Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 25 Jun 2011 02:49:47 +0000 Subject: Now that ia64 has been switched to the event timers, remove the conditional compilation work-arounds. --- sys/dev/acpica/acpi_cpu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c index b0a7210..d26903d 100644 --- a/sys/dev/acpica/acpi_cpu.c +++ b/sys/dev/acpica/acpi_cpu.c @@ -856,10 +856,8 @@ acpi_cpu_cx_list(struct acpi_cpu_softc *sc) sbuf_printf(&sb, "C%d/%d ", i + 1, sc->cpu_cx_states[i].trans_lat); if (sc->cpu_cx_states[i].type < ACPI_STATE_C3) sc->cpu_non_c3 = i; -#ifndef __ia64__ else cpu_can_deep_sleep = 1; -#endif } sbuf_trim(&sb); sbuf_finish(&sb); @@ -929,11 +927,9 @@ acpi_cpu_idle() /* Find the lowest state that has small enough latency. */ cx_next_idx = 0; -#ifndef __ia64__ if (cpu_disable_deep_sleep) i = min(sc->cpu_cx_lowest, sc->cpu_non_c3); else -#endif i = sc->cpu_cx_lowest; for (; i >= 0; i--) { if (sc->cpu_cx_states[i].trans_lat * 3 <= sc->cpu_prev_sleep) { -- cgit v1.1 From 34aad3a65eab8f3cea9aa2b8c85ae1ad9c49309e Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 25 Jun 2011 03:37:40 +0000 Subject: Update copyright. --- sys/ia64/ia64/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index 5f0e2fe..881c46f 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2005 Marcel Moolenaar + * Copyright (c) 2005, 2009-2011 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without -- cgit v1.1 From 31a073f6e13d66a4833c9ff57272a026464b4197 Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 25 Jun 2011 03:43:58 +0000 Subject: Replace the original copyright notice with my own. Everything in this file is written by me and has no bearing on the initial or original version. --- sys/ia64/ia64/interrupt.c | 52 ++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index f4e5594..27d5e60 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -1,41 +1,33 @@ -/* $FreeBSD$ */ -/* $NetBSD: interrupt.c,v 1.23 1998/02/24 07:38:01 thorpej Exp $ */ - /*- - * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * Copyright (c) 2010-2011 Marcel Moolenaar * All rights reserved. * - * Authors: Keith Bostic, Chris G. Demetriou - * - * Permission to use, copy, modify and distribute this software and - * its documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 + * 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. * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/*- - * Additional Copyright (c) 1997 by Matthew Jacob for NASA/Ames Research Center. - * Redistribute and modify at will, leaving only this additional copyright - * notice. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. */ #include "opt_ddb.h" -#include /* RCS ID & Copyright macro defns */ +#include +__FBSDID("$FreeBSD$"); #include #include -- cgit v1.1 From 57d68644db5c8ee303977b1240491c03faebbea3 Mon Sep 17 00:00:00 2001 From: avg Date: Sat, 25 Jun 2011 10:01:43 +0000 Subject: generic_stop_cpus: pull timeout logic from under DIAGNOSTIC ... and also increase the timeout. It's better to try to proceed somehow despite stuck CPUs than to hang indefinitely. Especially so during shutdown and when entering kdb or panic. Timeout value is still an aribitrary value. Timeout diagnostic is just a printf; the work on something more debuggable is planned by attilio. Need to be careful here as stop_cpus_hard is called very early while enetering kdb and soon(-ish) it may become called very early when entering panic. Reviewed by: attilio MFC after: 2 months --- sys/kern/subr_smp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index c38177b..0929ab9 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -236,12 +236,10 @@ generic_stop_cpus(cpuset_t map, u_int type) /* spin */ cpu_spinwait(); i++; -#ifdef DIAGNOSTIC - if (i == 100000) { + if (i == 100000000) { printf("timeout stopping cpus\n"); break; } -#endif } stopping_cpu = NOCPU; -- cgit v1.1 From 74e5eef4ea4a499154e939a75a53b61d33ff1fce Mon Sep 17 00:00:00 2001 From: avg Date: Sat, 25 Jun 2011 10:28:16 +0000 Subject: unconditionally stop other cpus when entering kdb in smp system ... and thus retire debug.kdb.stop_cpus tunable/sysctl. The knob was to work around CPU stopping issues, which since have been either fixed or greatly reduced. kdb should really operate in a special environment with scheduler stopped and interrupts disabled to provide deterministic debugging. Discussed with: attilio, rwatson X-MFC after: 2 months or never --- sys/kern/subr_kdb.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c index c2f6e99..2bc5ab2 100644 --- a/sys/kern/subr_kdb.c +++ b/sys/kern/subr_kdb.c @@ -88,20 +88,6 @@ SYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, CTLTYPE_INT | CTLFLAG_RW, NULL, 0, kdb_sysctl_trap_code, "I", "set to cause a page fault via code access"); /* - * Flag indicating whether or not to IPI the other CPUs to stop them on - * entering the debugger. Sometimes, this will result in a deadlock as - * stop_cpus() waits for the other cpus to stop, so we allow it to be - * disabled. In order to maximize the chances of success, use a hard - * stop for that. - */ -#ifdef SMP -static int kdb_stop_cpus = 1; -SYSCTL_INT(_debug_kdb, OID_AUTO, stop_cpus, CTLFLAG_RW | CTLFLAG_TUN, - &kdb_stop_cpus, 0, "stop other CPUs when entering the debugger"); -TUNABLE_INT("debug.kdb.stop_cpus", &kdb_stop_cpus); -#endif - -/* * Flag to indicate to debuggers why the debugger was entered. */ const char * volatile kdb_why = KDB_WHY_UNSET; @@ -515,9 +501,6 @@ kdb_trap(int type, int code, struct trapframe *tf) { struct kdb_dbbe *be; register_t intr; -#ifdef SMP - int did_stop_cpus; -#endif int handled; be = kdb_dbbe; @@ -531,8 +514,7 @@ kdb_trap(int type, int code, struct trapframe *tf) intr = intr_disable(); #ifdef SMP - if ((did_stop_cpus = kdb_stop_cpus) != 0) - stop_cpus_hard(PCPU_GET(other_cpus)); + stop_cpus_hard(PCPU_GET(other_cpus)); #endif kdb_active++; @@ -558,8 +540,7 @@ kdb_trap(int type, int code, struct trapframe *tf) kdb_active--; #ifdef SMP - if (did_stop_cpus) - restart_cpus(stopped_cpus); + restart_cpus(stopped_cpus); #endif intr_restore(intr); -- cgit v1.1 From 9e3d2fba08c8c32a52745a9fd210cc63d0802c4e Mon Sep 17 00:00:00 2001 From: pluknet Date: Sat, 25 Jun 2011 11:21:23 +0000 Subject: Add missing libkvm and libutil dependencies. Now libprocstat takes care of its own dependencies and does not require applications to specify them. Reviewed by: stas, jilles --- lib/libprocstat/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/libprocstat/Makefile b/lib/libprocstat/Makefile index e509169..05a64e7 100644 --- a/lib/libprocstat/Makefile +++ b/lib/libprocstat/Makefile @@ -19,6 +19,8 @@ INCS= libprocstat.h CFLAGS+= -I. -I${.CURDIR} -D_KVM_VNODE SHLIB_MAJOR= 1 WITHOUT_MAN= yes +DPADD= ${LIBKVM} ${LIBUTIL} +LDADD= -lkvm -lutil .if ${MK_NCP} != "no" CFLAGS+= -DLIBPROCSTAT_NWFS -- cgit v1.1 From 7571a340690fd7faeab96fe8ce55b12f82c862c8 Mon Sep 17 00:00:00 2001 From: jonathan Date: Sat, 25 Jun 2011 12:37:06 +0000 Subject: Remove redundant Capsicum sysctl. Since we're now declaring FEATURE(security_capabilities), there's no need for an explicit SYSCTL_NODE. Approved by: rwatson --- sys/kern/sys_capability.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c index 89dc923..c6d9826 100644 --- a/sys/kern/sys_capability.c +++ b/sys/kern/sys_capability.c @@ -64,13 +64,6 @@ __FBSDID("$FreeBSD$"); FEATURE(security_capabilities, "Capsicum Capability Mode"); /* - * We don't currently have any MIB entries for sysctls, but we do expose - * security.capabilities so that it's easy to tell if options CAPABILITIES is - * compiled into the kernel. - */ -SYSCTL_NODE(_security, OID_AUTO, capabilities, CTLFLAG_RW, 0, "Capsicum"); - -/* * System call to enter capability mode for the process. */ int -- cgit v1.1 From 0407380ca2f3a97fa613b6e84c1f802a283cd467 Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 25 Jun 2011 13:44:05 +0000 Subject: - Improve bus_autoconf tool. - Implement simple and generic language which can be used to describe any kind of device ID structures. - Fix endian issues. - Add an example format file. Suggested by: imp @ MFC after: 14 days --- tools/tools/bus_autoconf/Makefile | 5 +- tools/tools/bus_autoconf/bus_autoconf.c | 375 +++----------------- tools/tools/bus_autoconf/bus_autoconf.h | 55 --- tools/tools/bus_autoconf/bus_autoconf.sh | 57 +-- .../bus_autoconf/bus_autoconf_format_example.txt | 111 ++++++ tools/tools/bus_autoconf/bus_load_file.c | 72 ++++ tools/tools/bus_autoconf/bus_load_file.h | 33 ++ tools/tools/bus_autoconf/bus_sections.c | 223 ++++++++++++ tools/tools/bus_autoconf/bus_sections.h | 35 ++ tools/tools/bus_autoconf/bus_usb.c | 382 +++++++++++++++++++++ tools/tools/bus_autoconf/bus_usb.h | 73 ++++ 11 files changed, 1005 insertions(+), 416 deletions(-) create mode 100644 tools/tools/bus_autoconf/bus_autoconf_format_example.txt create mode 100644 tools/tools/bus_autoconf/bus_load_file.c create mode 100644 tools/tools/bus_autoconf/bus_load_file.h create mode 100644 tools/tools/bus_autoconf/bus_sections.c create mode 100644 tools/tools/bus_autoconf/bus_sections.h create mode 100644 tools/tools/bus_autoconf/bus_usb.c create mode 100644 tools/tools/bus_autoconf/bus_usb.h diff --git a/tools/tools/bus_autoconf/Makefile b/tools/tools/bus_autoconf/Makefile index c2f1b13..c7104de 100644 --- a/tools/tools/bus_autoconf/Makefile +++ b/tools/tools/bus_autoconf/Makefile @@ -36,7 +36,10 @@ PROG= bus_autoconf MAN= BINDIR?= /usr/local/bin -SRCS= bus_autoconf.c +SRCS+= bus_autoconf.c +SRCS+= bus_load_file.c +SRCS+= bus_sections.c +SRCS+= bus_usb.c WARNS= 6 diff --git a/tools/tools/bus_autoconf/bus_autoconf.c b/tools/tools/bus_autoconf/bus_autoconf.c index 3ddab5a..adbf6e4 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.c +++ b/tools/tools/bus_autoconf/bus_autoconf.c @@ -33,306 +33,23 @@ #include #include #include -#include -#include -#include -#include #include +#include +#include +#include #include "bus_autoconf.h" - -static char *type; -static char *file_name; -static const char *mode; - -struct usb_info; -static void usb_dump_sub(struct usb_device_id *, struct usb_info *); - -/* - * To ensure that the correct USB driver is loaded, the driver having - * the most information about the device must be probed first. Then - * more generic drivers shall be probed. - */ -static int -usb_compare(const void *_a, const void *_b) -{ - const struct usb_device_id *a = _a; - const struct usb_device_id *b = _b; - - /* vendor matches first */ - - if (a->match_flag_vendor > b->match_flag_vendor) - return (-1); - if (a->match_flag_vendor < b->match_flag_vendor) - return (1); - - /* product matches first */ - - if (a->match_flag_product > b->match_flag_product) - return (-1); - if (a->match_flag_product < b->match_flag_product) - return (1); - - /* device class matches first */ - - if (a->match_flag_dev_class > b->match_flag_dev_class) - return (-1); - if (a->match_flag_dev_class < b->match_flag_dev_class) - return (1); - - if (a->match_flag_dev_subclass > b->match_flag_dev_subclass) - return (-1); - if (a->match_flag_dev_subclass < b->match_flag_dev_subclass) - return (1); - - /* interface class matches first */ - - if (a->match_flag_int_class > b->match_flag_int_class) - return (-1); - if (a->match_flag_int_class < b->match_flag_int_class) - return (1); - - if (a->match_flag_int_subclass > b->match_flag_int_subclass) - return (-1); - if (a->match_flag_int_subclass < b->match_flag_int_subclass) - return (1); - - if (a->match_flag_int_protocol > b->match_flag_int_protocol) - return (-1); - if (a->match_flag_int_protocol < b->match_flag_int_protocol) - return (1); - - /* then sort according to value */ - - if (a->idVendor > b->idVendor) - return (1); - if (a->idVendor < b->idVendor) - return (-1); - if (a->idProduct > b->idProduct) - return (1); - if (a->idProduct < b->idProduct) - return (-1); - if (a->bDeviceClass > b->bDeviceClass) - return (1); - if (a->bDeviceClass < b->bDeviceClass) - return (-1); - if (a->bDeviceSubClass > b->bDeviceSubClass) - return (1); - if (a->bDeviceSubClass < b->bDeviceSubClass) - return (-1); - if (a->bDeviceProtocol > b->bDeviceProtocol) - return (1); - if (a->bDeviceProtocol < b->bDeviceProtocol) - return (-1); - if (a->bInterfaceClass > b->bInterfaceClass) - return (1); - if (a->bInterfaceClass < b->bInterfaceClass) - return (-1); - if (a->bInterfaceSubClass > b->bInterfaceSubClass) - return (1); - if (a->bInterfaceSubClass < b->bInterfaceSubClass) - return (-1); - if (a->bInterfaceProtocol > b->bInterfaceProtocol) - return (1); - if (a->bInterfaceProtocol < b->bInterfaceProtocol) - return (-1); - - /* in the end sort by module name */ - - return (strcmp(a->module_name, b->module_name)); -} - -static void -usb_sort(struct usb_device_id *id, uint32_t nid) -{ - qsort(id, nid, sizeof(*id), &usb_compare); -} - -struct usb_info { - uint8_t is_iface; - uint8_t is_any; - uint8_t is_vp; - uint8_t is_dev; -}; - -static void -usb_dump_sub(struct usb_device_id *id, struct usb_info *pinfo) -{ -#if USB_HAVE_COMPAT_LINUX - if (id->match_flags != 0) { - if (id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) - id->match_flag_vendor = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) - id->match_flag_product = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) - id->match_flag_dev_lo = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) - id->match_flag_dev_hi = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) - id->match_flag_dev_class = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) - id->match_flag_dev_subclass = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) - id->match_flag_dev_protocol = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) - id->match_flag_int_class = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) - id->match_flag_int_subclass = 1; - if (id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) - id->match_flag_int_protocol = 1; - id->match_flags = 0; - } -#endif - if (pinfo != NULL) { - - pinfo->is_iface = id->match_flag_int_class | - id->match_flag_int_protocol | - id->match_flag_int_subclass; - - pinfo->is_dev = id->match_flag_dev_class | - id->match_flag_dev_subclass; - - pinfo->is_vp = id->match_flag_vendor | - id->match_flag_product; - - pinfo->is_any = pinfo->is_vp + pinfo->is_dev + pinfo->is_iface; - } -} - -static char * -usb_trim(char *ptr) -{ - char *end; - - end = strchr(ptr, ' '); - if (end) - *end = 0; - return (ptr); -} - -static uint32_t -usb_dump(struct usb_device_id *id, uint32_t nid) -{ - uint32_t n = 1; - struct usb_info info; - - usb_dump_sub(id, &info); - - if (info.is_any) { - printf("nomatch 32 {\n" - " match \"bus\" \"uhub[0-9]+\";\n" - " match \"mode\" \"%s\";\n", mode); - } else { - return (n); - } - - if (id->match_flag_vendor) { - printf(" match \"vendor\" \"0x%04x\";\n", - id->idVendor); - } - if (id->match_flag_product) { - uint32_t x; - - if (info.is_any == 1 && info.is_vp == 1) { - /* try to join similar entries */ - while (n < nid) { - usb_dump_sub(id + n, &info); - - if (info.is_any != 1 || info.is_vp != 1) - break; - if (id[n].idVendor != id[0].idVendor) - break; - n++; - } - /* restore infos */ - usb_dump_sub(id, &info); - } - if (n == 1) { - printf(" match \"product\" \"0x%04x\";\n", - id->idProduct); - } else { - printf(" match \"product\" \"("); - - for (x = 0; x != n; x++) { - printf("0x%04x%s", id[x].idProduct, - (x == (n - 1)) ? "" : "|"); - } - - printf(")\";\n"); - } - } - if (id->match_flag_dev_class) { - printf(" match \"devclass\" \"0x%02x\";\n", - id->bDeviceClass); - } - if (id->match_flag_dev_subclass) { - printf(" match \"devsubclass\" \"0x%02x\";\n", - id->bDeviceSubClass); - } - if (id->match_flag_int_class) { - printf(" match \"intclass\" \"0x%02x\";\n", - id->bInterfaceClass); - } - if (id->match_flag_int_subclass) { - printf(" match \"intsubclass\" \"0x%02x\";\n", - id->bInterfaceSubClass); - } - if (id->match_flag_int_protocol) { - printf(" match \"intprotocol\" \"0x%02x\";\n", - id->bInterfaceProtocol); - } - printf(" action \"kldload %s\";\n" - "};\n\n", usb_trim(id->module_name)); - - return (n); -} - -static void -usb_parse_and_dump(int f, off_t size) -{ - struct usb_device_id *id; - uint32_t nid; - uint32_t x; - - if (size % sizeof(struct usb_device_id)) { - errx(EX_NOINPUT, "Size is not divisible by %d", - (int)sizeof(struct usb_device_id)); - } - lseek(f, 0, SEEK_SET); - - id = malloc(size); - if (id == NULL) { - errx(EX_SOFTWARE, "Out of memory"); - } - if (read(f, id, size) != size) { - err(EX_NOINPUT, "Cannot read all data"); - } - nid = size / sizeof(*id); - - for (x = 0; x != nid; x++) { - /* make sure flag bits are correct */ - usb_dump_sub(id + x, NULL); - /* zero terminate string */ - id[x].module_name[sizeof(id[0].module_name) - 1] = 0; - } - - usb_sort(id, nid); - - for (x = 0; x != nid;) - x += usb_dump(id + x, nid - x); - - free(id); - - printf("# %d %s entries processed\n\n", (int)nid, type); -} +#include "bus_sections.h" +#include "bus_load_file.h" +#include "bus_usb.h" static void usage(void) { fprintf(stderr, "bus_autoconf - devd config file generator\n" - " -i \n" - " -t \n" + " -i \n" + " -F \n" " -h show usage\n" ); exit(EX_USAGE); @@ -341,50 +58,68 @@ usage(void) int main(int argc, char **argv) { - const char *params = "i:ht:"; + const char *params = "i:F:h"; + char *fname; + char *section; + char *module; + char *postfix; + uint8_t *ptr; + uint32_t len; int c; - int f; - off_t off; + int any_opt = 0; while ((c = getopt(argc, argv, params)) != -1) { switch (c) { case 'i': - file_name = optarg; + fname = optarg; + load_file(fname, &ptr, &len); + + module = strchr(fname, ','); + if (module == NULL) { + errx(EX_USAGE, "Invalid input " + "file name '%s'", fname); + } + /* split module and section */ + *module++ = 0; + + /* remove postfix */ + postfix = strchr(module, '.'); + if (postfix) + *postfix = 0; + + /* get section name */ + section = fname; + + /* check section type */ + if (strncmp(section, "usb_", 4) == 0) + usb_import_entries(section, module, ptr, len); + else + errx(EX_USAGE, "Invalid section '%s'", section); + + free(ptr); + + any_opt = 1; break; - case 't': - type = optarg; + + case 'F': + fname = optarg; + load_file(fname, &ptr, &len); + format_parse_entries(ptr, len); + free(ptr); + + any_opt = 1; break; + default: usage(); break; } } - if (type == NULL || file_name == NULL) + if (any_opt == 0) usage(); - f = open(file_name, O_RDONLY); - if (f < 0) - err(EX_NOINPUT, "Cannot open file '%s'", file_name); - - off = lseek(f, 0, SEEK_END); - if (off <= 0) - err(EX_NOINPUT, "Cannot seek to end of file"); - - if (strcmp(type, "usb_host") == 0) { - mode = "host"; - usb_parse_and_dump(f, off); - } else if (strcmp(type, "usb_device") == 0) { - mode = "device"; - usb_parse_and_dump(f, off); - } else if (strcmp(type, "usb_dual") == 0) { - mode = "(host|device)"; - usb_parse_and_dump(f, off); - } else { - err(EX_USAGE, "Unsupported structure type: %s", type); - } - - close(f); + usb_dump_entries(); return (0); } diff --git a/tools/tools/bus_autoconf/bus_autoconf.h b/tools/tools/bus_autoconf/bus_autoconf.h index 7dbc486..0a1ca3f 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.h +++ b/tools/tools/bus_autoconf/bus_autoconf.h @@ -28,59 +28,4 @@ #ifndef _BUS_AUTOCONF_H_ #define _BUS_AUTOCONF_H_ -/* Make sure we get the have compat linux definition. */ -#include - -struct usb_device_id { - - /* Internal field */ - char module_name[32]; - - /* Hook for driver specific information */ - unsigned long driver_info; - - /* Used for product specific matches; the BCD range is inclusive */ - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice_lo; - uint16_t bcdDevice_hi; - - /* Used for device class matches */ - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - - /* Used for interface class matches */ - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - - /* Select which fields to match against */ - uint8_t match_flag_vendor:1; - uint8_t match_flag_product:1; - uint8_t match_flag_dev_lo:1; - uint8_t match_flag_dev_hi:1; - uint8_t match_flag_dev_class:1; - uint8_t match_flag_dev_subclass:1; - uint8_t match_flag_dev_protocol:1; - uint8_t match_flag_int_class:1; - uint8_t match_flag_int_subclass:1; - uint8_t match_flag_int_protocol:1; - -#if USB_HAVE_COMPAT_LINUX - /* which fields to match against */ - uint16_t match_flags; -#define USB_DEVICE_ID_MATCH_VENDOR 0x0001 -#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 -#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004 -#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008 -#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010 -#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020 -#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040 -#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 -#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 -#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 -#endif -}; - #endif /* _BUS_AUTOCONF_H_ */ diff --git a/tools/tools/bus_autoconf/bus_autoconf.sh b/tools/tools/bus_autoconf/bus_autoconf.sh index 21a4df0..1d1d038 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.sh +++ b/tools/tools/bus_autoconf/bus_autoconf.sh @@ -29,30 +29,6 @@ OS=FreeBSD DOLLAR=$ -cleanup() -{ - # Cleanup - rm -f usb_dual.ids - rm -f usb_host.ids - rm -f usb_device.ids -} - -usb_format() -{ - [ -f ${1} ] || return - - # Split into one and one record - split -b 32 ${1} ${1}. - - # Prefix each record by the module name - for G in $(ls ${1}.*) - do - printf "%-32s" ${3} >> ${2} - cat ${G} >> ${2} - rm -f ${G} - done -} - cat < /dev/null +[ -f temp.ids ] && cat temp.ids >> bus_autoconf_format.bin -# USB Host -objcopy -j usb_host_id -O binary ${F} temp.ids 2> /dev/null -usb_format temp.ids usb_host.ids ${H} +# USB Host mode +objcopy -j usb_host_id -O binary ${F} "usb_host_id,${G}" 2> /dev/null +[ -f "usb_host_id,${G}" ] && (echo -n " -i usb_host_id,${G}" >> bus_autoconf_args.txt) -# USB Device -objcopy -j usb_device_id -O binary ${F} temp.ids 2> /dev/null -usb_format temp.ids usb_device.ids ${H} +# USB Device mode +objcopy -j usb_device_id -O binary ${F} "usb_device_id,${G}" 2> /dev/null +[ -f "usb_device_id,${G}" ] && (echo -n " -i usb_device_id,${G}" >> bus_autoconf_args.txt) # USB Dual mode -objcopy -j usb_dual_id -O binary ${F} temp.ids 2> /dev/null -usb_format temp.ids usb_dual.ids ${H} +objcopy -j usb_dual_id -O binary ${F} "usb_dual_id,${G}" 2> /dev/null +[ -f "usb_dual_id,${G}" ] && (echo -n " -i usb_dual_id,${G}" >> bus_autoconf_args.txt) done # Dump all data -[ -f usb_dual.ids ] && bus_autoconf -i usb_dual.ids -t usb_dual -[ -f usb_host.ids ] && bus_autoconf -i usb_host.ids -t usb_host -[ -f usb_device.ids ] && bus_autoconf -i usb_device.ids -t usb_device +bus_autoconf -F bus_autoconf_format.bin $(cat bus_autoconf_args.txt) # Cleanup -cleanup +rm -f -- bus_autoconf_format.bin $(cat bus_autoconf_args.txt) diff --git a/tools/tools/bus_autoconf/bus_autoconf_format_example.txt b/tools/tools/bus_autoconf/bus_autoconf_format_example.txt new file mode 100644 index 0000000..e118f1f --- /dev/null +++ b/tools/tools/bus_autoconf/bus_autoconf_format_example.txt @@ -0,0 +1,111 @@ +/* $FreeBSD$ */ + +#if BYTE_ORDER == BIG_ENDIAN +#define U16_XOR "8" +#define U32_XOR "12" +#define U64_XOR "56" +#define U8_BITFIELD_XOR "7" +#define U16_BITFIELD_XOR "15" +#define U32_BITFIELD_XOR "31" +#define U64_BITFIELD_XOR "63" +#else +#define U16_XOR "0" +#define U32_XOR "0" +#define U64_XOR "0" +#define U8_BITFIELD_XOR "0" +#define U16_BITFIELD_XOR "0" +#define U32_BITFIELD_XOR "0" +#define U64_BITFIELD_XOR "0" +#endif + +#if USB_HAVE_COMPAT_LINUX +#define MFL_SIZE "1" +#else +#define MFL_SIZE "0" +#endif + +static const char __section("bus_autoconf_format") __used usb_id_format[] = { + + /* + * Declare three different sections that use the same format. + * All sizes are in bits. Fields cannot be greater than + * 8 bits in size. Bitfields having a size greater than 1 + * must fit within the byte in which the bitfield is defined. + */ + + "usb_host_id{256,:}" + "usb_device_id{256,:}" + "usb_dual_id{256,:}" + + /* + * Describe all fields in the usb_device_id structure + * which is found in sys/dev/usb/usbdi.h. + */ + +#if BITS_PER_LONG == 32 || BITS_PER_LONG == 64 + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" +#if BITS_PER_LONG == 64 + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" +#endif +#else +#error "Please update code." +#endif + + "idVendor[0]{" U16_XOR ",8}" + "idVendor[1]{" U16_XOR ",8}" + "idProduct[0]{" U16_XOR ",8}" + "idProduct[1]{" U16_XOR ",8}" + "bcdDevice_lo[0]{" U16_XOR ",8}" + "bcdDevice_lo[1]{" U16_XOR ",8}" + "bcdDevice_hi[0]{" U16_XOR ",8}" + "bcdDevice_hi[1]{" U16_XOR ",8}" + + "bDeviceClass{0,8}" + "bDeviceSubClass{0,8}" + "bDeviceProtocol{0,8}" + "bInterfaceClass{0,8}" + "bInterfaceSubClass{0,8}" + "bInterfaceProtocol{0,8}" + +/* NOTE: On big endian machines bitfields are bitreversed. */ + + "mf_vendor{" U8_BITFIELD_XOR ",1}" + "mf_product{" U8_BITFIELD_XOR ",1}" + "mf_dev_lo{" U8_BITFIELD_XOR ",1}" + "mf_dev_hi{" U8_BITFIELD_XOR ",1}" + + "mf_dev_class{" U8_BITFIELD_XOR ",1}" + "mf_dev_subclass{" U8_BITFIELD_XOR ",1}" + "mf_dev_protocol{" U8_BITFIELD_XOR ",1}" + "mf_int_class{" U8_BITFIELD_XOR ",1}" + + "mf_int_subclass{" U8_BITFIELD_XOR ",1}" + "mf_int_protocol{" U8_BITFIELD_XOR ",1}" + "unused{" U8_BITFIELD_XOR ",6}" + + "mfl_vendor{" U16_XOR "," MFL_SIZE "}" + "mfl_product{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_lo{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_hi{" U16_XOR "," MFL_SIZE "}" + + "mfl_dev_class{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_subclass{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_protocol{" U16_XOR "," MFL_SIZE "}" + "mfl_int_class{" U16_XOR "," MFL_SIZE "}" + + "mfl_int_subclass{" U16_XOR "," MFL_SIZE "}" + "mfl_int_protocol{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" +}; diff --git a/tools/tools/bus_autoconf/bus_load_file.c b/tools/tools/bus_autoconf/bus_load_file.c new file mode 100644 index 0000000..88f806a --- /dev/null +++ b/tools/tools/bus_autoconf/bus_load_file.c @@ -0,0 +1,72 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "bus_load_file.h" + +void +load_file(const char *fname, uint8_t **pptr, uint32_t *plen) +{ + uint8_t *ptr; + uint32_t len; + off_t off; + int f; + + f = open(fname, O_RDONLY); + if (f < 0) + err(EX_NOINPUT, "Cannot open file '%s'", fname); + + off = lseek(f, 0, SEEK_END); + if (off <= 0) + err(EX_NOINPUT, "Cannot seek to end of file"); + + if (lseek(f, 0, SEEK_SET) < 0) + err(EX_NOINPUT, "Cannot seek to beginning of file"); + + len = off; + if (len != off) + err(EX_NOINPUT, "File '%s' is too big", fname); + + ptr = malloc(len); + if (ptr == NULL) + errx(EX_SOFTWARE, "Out of memory"); + + if (read(f, ptr, len) != len) + err(EX_NOINPUT, "Cannot read all data"); + + close(f); + + *pptr = ptr; + *plen = len; +} diff --git a/tools/tools/bus_autoconf/bus_load_file.h b/tools/tools/bus_autoconf/bus_load_file.h new file mode 100644 index 0000000..57e7739 --- /dev/null +++ b/tools/tools/bus_autoconf/bus_load_file.h @@ -0,0 +1,33 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef _BUS_LOAD_FILE_H_ +#define _BUS_LOAD_FILE_H_ + +void load_file(const char *, uint8_t **, uint32_t *); + +#endif /* _BUS_LOAD_FILE_H_ */ diff --git a/tools/tools/bus_autoconf/bus_sections.c b/tools/tools/bus_autoconf/bus_sections.c new file mode 100644 index 0000000..c326048 --- /dev/null +++ b/tools/tools/bus_autoconf/bus_sections.c @@ -0,0 +1,223 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "bus_sections.h" + +#define MAX_STRING 64 + +struct format_info; +typedef TAILQ_HEAD(,format_info) format_info_head_t; +typedef TAILQ_ENTRY(format_info) format_info_entry_t; + +static format_info_head_t format_head = TAILQ_HEAD_INITIALIZER(format_head); + +struct format_info { + format_info_entry_t entry; + format_info_head_t fields; + char name[MAX_STRING]; + uint16_t bit_offset; + uint16_t bit_size; +}; + +static struct format_info * +format_info_new(char *pstr, uint16_t bo, uint16_t bs) +{ + struct format_info *pfi; + + pfi = malloc(sizeof(*pfi)); + if (pfi == NULL) + errx(EX_SOFTWARE, "Out of memory."); + + memset(pfi, 0, sizeof(*pfi)); + + TAILQ_INIT(&pfi->fields); + + strlcpy(pfi->name, pstr, sizeof(pfi->name)); + pfi->bit_offset = bo; + pfi->bit_size = bs; + return (pfi); +} + +static const struct format_info * +format_get_section(const char *section) +{ + const struct format_info *psub; + static const struct format_info *psub_last; + static const char *psub_cache; + + if (psub_cache && strcmp(psub_cache, section) == 0) + return (psub_last); + + TAILQ_FOREACH(psub, &format_head, entry) { + if (strcmp(section, psub->name) == 0) { + psub_cache = section; + psub_last = psub; + return (psub); + } + } + warnx("Section '%s' not found", section); + psub_cache = section; + psub_last = psub; + return (NULL); +} + +uint16_t +format_get_section_size(const char *section) +{ + const struct format_info *pfi; + + pfi = format_get_section(section); + if (pfi == NULL) + return (0); + + return ((pfi->bit_offset + 7) / 8); +} + + +uint8_t +format_get_field(const char *section, const char *field, + const uint8_t *ptr, uint16_t size) +{ + const struct format_info *pfi; + const struct format_info *psub; + uint16_t rem; + uint16_t off; + uint16_t sz; + + pfi = format_get_section(section); + if (pfi == NULL) + return (0); + + /* skip until we find the fields */ + while (pfi && TAILQ_FIRST(&pfi->fields) == NULL) + pfi = TAILQ_NEXT(pfi, entry); + + if (pfi == NULL) + return (0); + + TAILQ_FOREACH(psub, &pfi->fields, entry) { + if (strcmp(field, psub->name) == 0) { + + /* range check */ + if (((psub->bit_offset + psub->bit_size) / 8) > size) + return (0); + + /* compute byte offset */ + rem = psub->bit_offset & 7; + off = psub->bit_offset / 8; + sz = psub->bit_size; + + /* extract bit-field */ + return ((ptr[off] >> rem) & ((1 << sz) - 1)); + } + } + warnx("Field '%s' not found in '%s'", field, pfi->name); + return (0); +} + +void +format_parse_entries(const uint8_t *ptr, uint32_t len) +{ + static const char *command_list = "012345678:"; + const char *cmd; + struct format_info *pfi; + struct format_info *pfi_last = NULL; + char linebuf[3][MAX_STRING]; + uint32_t off = 0; + uint16_t bit_offset = 0; + uint8_t state = 0; + uint8_t cmd_index; + int c; + + /* + * The format we are parsing: + * {string,string}{...} + */ + while (len--) { + c = *(ptr++); + + /* skip some characters */ + if (c == 0 || c == '\n' || c == '\r' || c == ' ' || c == '\t') + continue; + + /* accumulate non-field delimiters */ + if (strchr("{,}", c) == NULL) { + if (off < (MAX_STRING - 1)) { + linebuf[state][off] = c; + off++; + } + continue; + } + /* parse keyword */ + linebuf[state][off] = 0; + off = 0; + state++; + if (state == 3) { + /* check for command in command list */ + cmd = strchr(command_list, linebuf[2][0]); + if (cmd != NULL) + cmd_index = cmd - command_list; + else + cmd_index = 255; + + /* + * Check for new field, format is: + * + * {bit_offset_xor, bit_size} + */ + if (cmd_index < 9 && pfi_last != NULL) { + pfi = format_info_new(linebuf[0], bit_offset ^ + atoi(linebuf[1]), cmd_index); + TAILQ_INSERT_TAIL(&pfi_last->fields, pfi, entry); + bit_offset += cmd_index; + } + /* + * Check for new section, format is: + * + * {section_bit_size, :} + */ + if (cmd_index == 9) { + pfi_last = format_info_new(linebuf[0], + atoi(linebuf[1]), cmd_index); + TAILQ_INSERT_TAIL(&format_head, pfi_last, entry); + bit_offset = 0; + } + state = 0; + continue; + } + } +} diff --git a/tools/tools/bus_autoconf/bus_sections.h b/tools/tools/bus_autoconf/bus_sections.h new file mode 100644 index 0000000..2c4c6fc --- /dev/null +++ b/tools/tools/bus_autoconf/bus_sections.h @@ -0,0 +1,35 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef _BUS_SECTIONS_H_ +#define _BUS_SECTIONS_H_ + +uint16_t format_get_section_size(const char *); +uint8_t format_get_field(const char *, const char *, const uint8_t *, uint16_t); +void format_parse_entries(const uint8_t *, uint32_t); + +#endif /* _BUS_SECTIONS_H_ */ diff --git a/tools/tools/bus_autoconf/bus_usb.c b/tools/tools/bus_autoconf/bus_usb.c new file mode 100644 index 0000000..e3d60e8 --- /dev/null +++ b/tools/tools/bus_autoconf/bus_usb.c @@ -0,0 +1,382 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bus_autoconf.h" +#include "bus_sections.h" +#include "bus_usb.h" + +struct usb_blob; +typedef TAILQ_HEAD(,usb_blob) usb_blob_head_t; +typedef TAILQ_ENTRY(usb_blob) usb_blob_entry_t; + +static usb_blob_head_t usb_blob_head = TAILQ_HEAD_INITIALIZER(usb_blob_head); +static uint32_t usb_blob_count; + +struct usb_blob { + usb_blob_entry_t entry; + struct usb_device_id temp; +}; + +/* + * To ensure that the correct USB driver is loaded, the driver having + * the most information about the device must be probed first. Then + * more generic drivers shall be probed. + */ +static int +usb_compare(const void *_a, const void *_b) +{ + const struct usb_device_id *a = _a; + const struct usb_device_id *b = _b; + int retval; + + /* vendor matches first */ + + if (a->match_flag_vendor > b->match_flag_vendor) + return (-1); + if (a->match_flag_vendor < b->match_flag_vendor) + return (1); + + /* product matches first */ + + if (a->match_flag_product > b->match_flag_product) + return (-1); + if (a->match_flag_product < b->match_flag_product) + return (1); + + /* device class matches first */ + + if (a->match_flag_dev_class > b->match_flag_dev_class) + return (-1); + if (a->match_flag_dev_class < b->match_flag_dev_class) + return (1); + + if (a->match_flag_dev_subclass > b->match_flag_dev_subclass) + return (-1); + if (a->match_flag_dev_subclass < b->match_flag_dev_subclass) + return (1); + + /* interface class matches first */ + + if (a->match_flag_int_class > b->match_flag_int_class) + return (-1); + if (a->match_flag_int_class < b->match_flag_int_class) + return (1); + + if (a->match_flag_int_subclass > b->match_flag_int_subclass) + return (-1); + if (a->match_flag_int_subclass < b->match_flag_int_subclass) + return (1); + + if (a->match_flag_int_protocol > b->match_flag_int_protocol) + return (-1); + if (a->match_flag_int_protocol < b->match_flag_int_protocol) + return (1); + + /* then sort according to value */ + + if (a->idVendor > b->idVendor) + return (1); + if (a->idVendor < b->idVendor) + return (-1); + if (a->idProduct > b->idProduct) + return (1); + if (a->idProduct < b->idProduct) + return (-1); + if (a->bDeviceClass > b->bDeviceClass) + return (1); + if (a->bDeviceClass < b->bDeviceClass) + return (-1); + if (a->bDeviceSubClass > b->bDeviceSubClass) + return (1); + if (a->bDeviceSubClass < b->bDeviceSubClass) + return (-1); + if (a->bDeviceProtocol > b->bDeviceProtocol) + return (1); + if (a->bDeviceProtocol < b->bDeviceProtocol) + return (-1); + if (a->bInterfaceClass > b->bInterfaceClass) + return (1); + if (a->bInterfaceClass < b->bInterfaceClass) + return (-1); + if (a->bInterfaceSubClass > b->bInterfaceSubClass) + return (1); + if (a->bInterfaceSubClass < b->bInterfaceSubClass) + return (-1); + if (a->bInterfaceProtocol > b->bInterfaceProtocol) + return (1); + if (a->bInterfaceProtocol < b->bInterfaceProtocol) + return (-1); + + /* in the end sort by module name and mode */ + + retval = strcmp(a->module_name, b->module_name); + if (retval == 0) + retval = strcmp(a->module_mode, b->module_mode); + return (retval); +} + +static void +usb_sort_entries(struct usb_device_id *id, uint32_t nid) +{ + qsort(id, nid, sizeof(*id), &usb_compare); +} + +static void +usb_import_entry(struct usb_device_id *id, const char *type, + const char *module, const uint8_t *ptr, uint16_t size) +{ + const char *mode; + + if (strstr(type, "_host_")) + mode = "host"; + else if (strstr(type, "_device_")) + mode = "device"; + else + mode = "(host|device)"; + + strlcpy(id->module_name, module, sizeof(id->module_name)); + strlcpy(id->module_mode, mode, sizeof(id->module_mode)); + + /* import data from binary object */ + + if (format_get_field(type, "mfl_vendor", ptr, size)) + id->match_flag_vendor = 1; + if (format_get_field(type, "mfl_product", ptr, size)) + id->match_flag_product = 1; + if (format_get_field(type, "mfl_dev_lo", ptr, size)) + id->match_flag_dev_lo = 1; + if (format_get_field(type, "mfl_dev_hi", ptr, size)) + id->match_flag_dev_hi = 1; + if (format_get_field(type, "mfl_dev_class", ptr, size)) + id->match_flag_dev_class = 1; + if (format_get_field(type, "mfl_dev_subclass", ptr, size)) + id->match_flag_dev_subclass = 1; + if (format_get_field(type, "mfl_dev_protocol", ptr, size)) + id->match_flag_dev_protocol = 1; + if (format_get_field(type, "mfl_int_class", ptr, size)) + id->match_flag_int_class = 1; + if (format_get_field(type, "mfl_int_subclass", ptr, size)) + id->match_flag_int_subclass = 1; + if (format_get_field(type, "mfl_int_protocol", ptr, size)) + id->match_flag_int_protocol = 1; + + id->idVendor = format_get_field(type, "idVendor[0]", ptr, size) | + (format_get_field(type, "idVendor[1]", ptr, size) << 8); + id->idProduct = format_get_field(type, "idProduct[0]", ptr, size) | + (format_get_field(type, "idProduct[1]", ptr, size) << 8); + + id->bcdDevice_lo = format_get_field(type, "bcdDevice_lo[0]", ptr, size) | + (format_get_field(type, "bcdDevice_lo[1]", ptr, size) << 8); + + id->bcdDevice_hi = format_get_field(type, "bcdDevice_hi[0]", ptr, size) | + (format_get_field(type, "bcdDevice_hi[1]", ptr, size) << 8); + + id->bDeviceClass = format_get_field(type, "bDeviceClass", ptr, size); + id->bDeviceSubClass = format_get_field(type, "bDeviceSubClass", ptr, size); + id->bDeviceProtocol = format_get_field(type, "bDeviceProtocol", ptr, size); + + id->bInterfaceClass = format_get_field(type, "bInterfaceClass", ptr, size); + id->bInterfaceSubClass = format_get_field(type, "bInterfaceSubClass", ptr, size); + id->bInterfaceProtocol = format_get_field(type, "bInterfaceProtocol", ptr, size); + + if (format_get_field(type, "mf_vendor", ptr, size)) + id->match_flag_vendor = 1; + if (format_get_field(type, "mf_product", ptr, size)) + id->match_flag_product = 1; + if (format_get_field(type, "mf_dev_lo", ptr, size)) + id->match_flag_dev_lo = 1; + if (format_get_field(type, "mf_dev_hi", ptr, size)) + id->match_flag_dev_hi = 1; + if (format_get_field(type, "mf_dev_class", ptr, size)) + id->match_flag_dev_class = 1; + if (format_get_field(type, "mf_dev_subclass", ptr, size)) + id->match_flag_dev_subclass = 1; + if (format_get_field(type, "mf_dev_protocol", ptr, size)) + id->match_flag_dev_protocol = 1; + if (format_get_field(type, "mf_int_class", ptr, size)) + id->match_flag_int_class = 1; + if (format_get_field(type, "mf_int_subclass", ptr, size)) + id->match_flag_int_subclass = 1; + if (format_get_field(type, "mf_int_protocol", ptr, size)) + id->match_flag_int_protocol = 1; + + /* compute some internal fields */ + id->is_iface = id->match_flag_int_class | + id->match_flag_int_protocol | + id->match_flag_int_subclass; + + id->is_dev = id->match_flag_dev_class | + id->match_flag_dev_subclass; + + id->is_vp = id->match_flag_vendor | + id->match_flag_product; + + id->is_any = id->is_vp + id->is_dev + id->is_iface; +} + +static uint32_t +usb_dump(struct usb_device_id *id, uint32_t nid) +{ + uint32_t n = 1; + + if (id->is_any) { + printf("nomatch 32 {\n" + " match \"bus\" \"uhub[0-9]+\";\n" + " match \"mode\" \"%s\";\n", id->module_mode); + } else { + printf("# skipped entry on module %s\n", + id->module_name); + return (n); + } + + if (id->match_flag_vendor) { + printf(" match \"vendor\" \"0x%04x\";\n", + id->idVendor); + } + if (id->match_flag_product) { + uint32_t x; + + if (id->is_any == 1 && id->is_vp == 1) { + /* try to join similar entries */ + while (n < nid) { + if (id[n].is_any != 1 || id[n].is_vp != 1) + break; + if (id[n].idVendor != id[0].idVendor) + break; + n++; + } + } + if (n == 1) { + printf(" match \"product\" \"0x%04x\";\n", + id->idProduct); + } else { + printf(" match \"product\" \"("); + + for (x = 0; x != n; x++) { + printf("0x%04x%s", id[x].idProduct, + (x == (n - 1)) ? "" : "|"); + } + + printf(")\";\n"); + } + } + if (id->match_flag_dev_class) { + printf(" match \"devclass\" \"0x%02x\";\n", + id->bDeviceClass); + } + if (id->match_flag_dev_subclass) { + printf(" match \"devsubclass\" \"0x%02x\";\n", + id->bDeviceSubClass); + } + if (id->match_flag_int_class) { + printf(" match \"intclass\" \"0x%02x\";\n", + id->bInterfaceClass); + } + if (id->match_flag_int_subclass) { + printf(" match \"intsubclass\" \"0x%02x\";\n", + id->bInterfaceSubClass); + } + if (id->match_flag_int_protocol) { + printf(" match \"intprotocol\" \"0x%02x\";\n", + id->bInterfaceProtocol); + } + printf(" action \"kldload %s\";\n" + "};\n\n", id->module_name); + + return (n); +} + +void +usb_import_entries(const char *section, const char *module, + const uint8_t *ptr, uint32_t len) +{ + struct usb_blob *pub; + uint32_t section_size; + uint32_t off; + + section_size = format_get_section_size(section); + if (section_size == 0) { + errx(EX_DATAERR, "Invalid or non-existing " + "section format '%s'", section); + } + if (len % section_size) { + errx(EX_DATAERR, "Length %d is not " + "divisible by %d. Section format '%s'", + len, section_size, section); + } + for (off = 0; off != len; off += section_size) { + pub = malloc(sizeof(*pub)); + if (pub == NULL) + errx(EX_SOFTWARE, "Out of memory"); + + memset(pub, 0, sizeof(*pub)); + + usb_import_entry(&pub->temp, section, + module, ptr + off, section_size); + + TAILQ_INSERT_TAIL(&usb_blob_head, pub, entry); + + usb_blob_count++; + if (usb_blob_count == 0) + errx(EX_SOFTWARE, "Too many entries"); + } +} + +void +usb_dump_entries(void) +{ + struct usb_blob *pub; + struct usb_device_id *id; + uint32_t x; + + id = malloc(usb_blob_count * sizeof(*id)); + if (id == NULL) + errx(EX_SOFTWARE, "Out of memory"); + + /* make linear array of all USB blobs */ + x = 0; + TAILQ_FOREACH(pub, &usb_blob_head, entry) + id[x++] = pub->temp; + + usb_sort_entries(id, usb_blob_count); + + for (x = 0; x != usb_blob_count;) + x += usb_dump(id + x, usb_blob_count - x); + + free(id); + + printf("# %d USB entries processed\n\n", usb_blob_count); +} diff --git a/tools/tools/bus_autoconf/bus_usb.h b/tools/tools/bus_autoconf/bus_usb.h new file mode 100644 index 0000000..378df9a --- /dev/null +++ b/tools/tools/bus_autoconf/bus_usb.h @@ -0,0 +1,73 @@ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 2011 Hans Petter Selasky. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef _BUS_USB_H_ +#define _BUS_USB_H_ + +struct usb_device_id { + + /* Internal fields */ + char module_name[32]; + char module_mode[32]; + uint8_t is_iface; + uint8_t is_vp; + uint8_t is_dev; + uint8_t is_any; + + /* Used for product specific matches; the BCD range is inclusive */ + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice_lo; + uint16_t bcdDevice_hi; + + /* Used for device class matches */ + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + + /* Used for interface class matches */ + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + + /* Select which fields to match against */ + uint8_t match_flag_vendor:1; + uint8_t match_flag_product:1; + uint8_t match_flag_dev_lo:1; + uint8_t match_flag_dev_hi:1; + uint8_t match_flag_dev_class:1; + uint8_t match_flag_dev_subclass:1; + uint8_t match_flag_dev_protocol:1; + uint8_t match_flag_int_class:1; + uint8_t match_flag_int_subclass:1; + uint8_t match_flag_int_protocol:1; +}; + +void usb_import_entries(const char *, const char *, const uint8_t *, uint32_t); +void usb_dump_entries(void); + +#endif /* _BUS_USB_H_ */ -- cgit v1.1 From 9a21b2d946d3dfde68d1c0d44c0e676b2b2fd166 Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 25 Jun 2011 15:22:44 +0000 Subject: - Need to respect the module name and the USB mode when accumulating device ID's. - Be more verbose on file seek failures. Allow a file size of zero. - Improve the wrapper shell. MFC after: 14 days --- tools/tools/bus_autoconf/bus_autoconf.sh | 18 ++++++++++++------ tools/tools/bus_autoconf/bus_load_file.c | 12 ++++++++---- tools/tools/bus_autoconf/bus_usb.c | 4 ++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tools/tools/bus_autoconf/bus_autoconf.sh b/tools/tools/bus_autoconf/bus_autoconf.sh index 1d1d038..c99df91 100644 --- a/tools/tools/bus_autoconf/bus_autoconf.sh +++ b/tools/tools/bus_autoconf/bus_autoconf.sh @@ -28,6 +28,7 @@ OS=FreeBSD DOLLAR=$ +OBJCOPY=objcopy cat < /dev/null -[ -f temp.ids ] && cat temp.ids >> bus_autoconf_format.bin +${OBJCOPY} -j bus_autoconf_format -O binary ${F} bus_autoconf.ids 2> /dev/null +[ -f bus_autoconf.ids ] && cat bus_autoconf.ids >> bus_autoconf_format.bin # USB Host mode -objcopy -j usb_host_id -O binary ${F} "usb_host_id,${G}" 2> /dev/null +${OBJCOPY} -j usb_host_id -O binary ${F} "usb_host_id,${G}" 2> /dev/null [ -f "usb_host_id,${G}" ] && (echo -n " -i usb_host_id,${G}" >> bus_autoconf_args.txt) # USB Device mode -objcopy -j usb_device_id -O binary ${F} "usb_device_id,${G}" 2> /dev/null +${OBJCOPY} -j usb_device_id -O binary ${F} "usb_device_id,${G}" 2> /dev/null [ -f "usb_device_id,${G}" ] && (echo -n " -i usb_device_id,${G}" >> bus_autoconf_args.txt) # USB Dual mode -objcopy -j usb_dual_id -O binary ${F} "usb_dual_id,${G}" 2> /dev/null +${OBJCOPY} -j usb_dual_id -O binary ${F} "usb_dual_id,${G}" 2> /dev/null [ -f "usb_dual_id,${G}" ] && (echo -n " -i usb_dual_id,${G}" >> bus_autoconf_args.txt) done @@ -69,4 +71,8 @@ done bus_autoconf -F bus_autoconf_format.bin $(cat bus_autoconf_args.txt) # Cleanup -rm -f -- bus_autoconf_format.bin $(cat bus_autoconf_args.txt) +rm -f -- \ + $(cat bus_autoconf_args.txt) \ + bus_autoconf_args.txt \ + bus_autoconf_format.bin \ + bus_autoconf.ids diff --git a/tools/tools/bus_autoconf/bus_load_file.c b/tools/tools/bus_autoconf/bus_load_file.c index 88f806a..527e5bc 100644 --- a/tools/tools/bus_autoconf/bus_load_file.c +++ b/tools/tools/bus_autoconf/bus_load_file.c @@ -48,11 +48,15 @@ load_file(const char *fname, uint8_t **pptr, uint32_t *plen) err(EX_NOINPUT, "Cannot open file '%s'", fname); off = lseek(f, 0, SEEK_END); - if (off <= 0) - err(EX_NOINPUT, "Cannot seek to end of file"); + if (off < 0) { + err(EX_NOINPUT, "Cannot seek to " + "end of file '%s'", fname); + } - if (lseek(f, 0, SEEK_SET) < 0) - err(EX_NOINPUT, "Cannot seek to beginning of file"); + if (lseek(f, 0, SEEK_SET) < 0) { + err(EX_NOINPUT, "Cannot seek to " + "beginning of file '%s'", fname); + } len = off; if (len != off) diff --git a/tools/tools/bus_autoconf/bus_usb.c b/tools/tools/bus_autoconf/bus_usb.c index e3d60e8..ab794c1 100644 --- a/tools/tools/bus_autoconf/bus_usb.c +++ b/tools/tools/bus_autoconf/bus_usb.c @@ -276,6 +276,10 @@ usb_dump(struct usb_device_id *id, uint32_t nid) break; if (id[n].idVendor != id[0].idVendor) break; + if (strcmp(id[n].module_name, id[0].module_name)) + break; + if (strcmp(id[n].module_mode, id[0].module_mode)) + break; n++; } } -- cgit v1.1 From 19e89d19b5adf1c119f999703efcecc4f93d652e Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 25 Jun 2011 15:42:33 +0000 Subject: - Move auto-load devd config file into etc/defaults folder. - Regenerate file after bugfix in the generator. Suggested by: Jeremy Messenger MFC after: 14 days --- etc/defaults/Makefile | 2 +- etc/defaults/devd.conf | 4275 ++++++++++++++++++++++++++++++++++++++++++++++++ etc/devd/bus_auto.conf | 2381 --------------------------- 3 files changed, 4276 insertions(+), 2382 deletions(-) create mode 100644 etc/defaults/devd.conf delete mode 100644 etc/devd/bus_auto.conf diff --git a/etc/defaults/Makefile b/etc/defaults/Makefile index c6555e6..0d3a81a 100644 --- a/etc/defaults/Makefile +++ b/etc/defaults/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -FILES= bluetooth.device.conf devfs.rules periodic.conf rc.conf +FILES= bluetooth.device.conf devd.conf devfs.rules periodic.conf rc.conf NO_OBJ= FILESDIR= /etc/defaults diff --git a/etc/defaults/devd.conf b/etc/defaults/devd.conf new file mode 100644 index 0000000..5dbbd0a --- /dev/null +++ b/etc/defaults/devd.conf @@ -0,0 +1,4275 @@ +# +# $FreeBSD$ +# +# This file was automatically generated by "tools/bus_autoconf.sh". +# Please do not edit! +# + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1290"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1292"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1294"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1297"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0104"; + match "product" "0x00be"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0123"; + match "product" "0x0001"; + action "kldload uep"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03e8"; + match "product" "0x0008"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03eb"; + match "product" "0x2109"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0x0121"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x1016|0x1116|0x1216)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x1b1d|0x1e1d)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x2016|0x2116|0x2216|0x3016|0x3116|0x3216)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0x3524"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x4016|0x4116|0x4216|0x5016|0x5116|0x5216)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0x811c"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0xca02"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0402"; + match "product" "0x5632"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0403"; + match "product" "(0x6001|0x6004|0x6010|0x6011|0x8372|0x9e90|0xcc48|0xcc49|0xcc4a|0xd678|0xe6c8|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xee18|0xf608|0xf60b|0xf850|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfc08|0xfc09|0xfc0b|0xfc0c|0xfc0d|0xfc82)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0408"; + match "product" "0x0304"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0408"; + match "product" "(0x1000|0xea02|0xea03|0xea04|0xea05|0xea06)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0409"; + match "product" "(0x00d5|0x00d6|0x00d7|0x8024|0x8025)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x0001|0x0005|0x0009)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x0012"; + action "kldload if_rue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x003d"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x005e|0x0066|0x0067)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x006e"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x008b"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x00b3"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x00d8|0x00d9)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x00da"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x00e8"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x0116|0x0119)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x012e"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x0137"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x0148|0x0150|0x015d|0x016f)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0413"; + match "product" "0x2101"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0423"; + match "product" "(0x000a|0x000c)"; + action "kldload if_cue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x043e"; + match "product" "0x9c01"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045a"; + match "product" "(0x5001|0x5002)"; + action "kldload urio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045b"; + match "product" "0x0053"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045e"; + match "product" "0x0079"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045e"; + match "product" "0x007a"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045e"; + match "product" "(0x00ce|0x0400|0x0401|0x0402|0x0403|0x0404|0x0405|0x0406|0x0407|0x0408|0x0409|0x040a|0x040b|0x040c|0x040d|0x040e|0x040f|0x0410|0x0411|0x0412|0x0413|0x0414|0x0415|0x0416|0x0417|0x0432|0x0433|0x0434|0x0435|0x0436|0x0437|0x0438|0x0439|0x043a|0x043b|0x043c|0x043d|0x043e|0x043f|0x0440|0x0441|0x0442|0x0443|0x0444|0x0445|0x0446|0x0447|0x0448|0x0449|0x044a|0x044b|0x044c|0x044d|0x044e|0x044f|0x0450|0x0451|0x0452|0x0453|0x0454|0x0455|0x0456|0x0457|0x0458|0x0459|0x045a|0x045b|0x045c|0x045d|0x045e|0x045f|0x0460|0x0461|0x0462|0x0463|0x0464|0x0465|0x0466|0x0467|0x0468|0x0469|0x046a|0x046b|0x046c|0x046d|0x046e|0x046f|0x0470|0x0471|0x0472|0x0473|0x0474|0x0475|0x0476|0x0477|0x0478|0x0479|0x047a|0x047b|0x04c8|0x04c9|0x04ca|0x04cb|0x04cc|0x04cd|0x04ce|0x04d7|0x04d8|0x04d9|0x04da|0x04db|0x04dc|0x04dd|0x04de|0x04df|0x04e0|0x04e1|0x04e2|0x04e3|0x04e4|0x04e5|0x04e6|0x04e7|0x04e8|0x04e9|0x04ea)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0471"; + match "product" "0x066a"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0471"; + match "product" "0x1236"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0471"; + match "product" "0x200f"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0482"; + match "product" "0x0203"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0489"; + match "product" "(0xe000|0xe003)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x049f"; + match "product" "(0x0003|0x0032)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x049f"; + match "product" "0x505a"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a4"; + match "product" "0x0014"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a5"; + match "product" "0x4027"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a5"; + match "product" "0x4068"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04ad"; + match "product" "(0x0301|0x0302|0x0303|0x0306)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b4"; + match "product" "0x1002"; + action "kldload ufm"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b7"; + match "product" "0x0531"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b8"; + match "product" "(0x0521|0x0522)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "0x0901"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "(0x0904|0x0913)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "0x0930"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "(0x0944|0x0945|0x0947|0x0948)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "(0x0a03|0x0a0e)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bf"; + match "product" "(0x0115|0x0117)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04c5"; + match "product" "(0x1058|0x1079)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04da"; + match "product" "0x2500"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04da"; + match "product" "0x3900"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04dd"; + match "product" "(0x8004|0x8005|0x8006|0x8007|0x9031)"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04dd"; + match "product" "(0x9102|0x9121|0x9123|0x9151|0x91ac|0x9242)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "(0x5f00|0x5f01|0x5f02|0x5f03|0x5f04)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "0x6601"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "(0x6611|0x6613|0x6615|0x6617|0x6619|0x661b|0x662e|0x6630|0x6632)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "0x8001"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04f1"; + match "product" "0x3008"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04f1"; + match "product" "(0x3011|0x3012)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0502"; + match "product" "(0x1631|0x1632|0x16e1|0x16e2|0x16e3)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0506"; + match "product" "(0x03e8|0x11f8)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0506"; + match "product" "0x4601"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0103"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0109"; + action "kldload umct"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0121"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0257"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0409"; + action "kldload umct"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x1203"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x4050"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x5055"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x7050"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "(0x7050|0x7051)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x705a"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x705c"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x705e"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "(0x8053|0x805c|0x815c|0x825a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x905b"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x935a"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0525"; + match "product" "0x1080"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0525"; + match "product" "0xa4a2"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0536"; + match "product" "0x01a0"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0543"; + match "product" "(0x0ed9|0x1527|0x1529|0x152b|0x152e|0x1921|0x1922|0x1923)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0547"; + match "product" "0x2008"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0547"; + match "product" "0x2720"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x054c"; + match "product" "(0x0038|0x0066|0x0095|0x009a|0x00da|0x0169)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x054c"; + match "product" "0x0437"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2002"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2007"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2008"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2009"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x4000"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x055d"; + match "product" "0x2018"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0565"; + match "product" "0x0001"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0565"; + match "product" "(0x0002|0x0003|0x0005)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0567"; + match "product" "(0x2000|0x2002)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056c"; + match "product" "0x8007"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "(0x200c|0x4002|0x4005|0x400b|0x4010)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "(0x5003|0x5004)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "0xabc1"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x057c"; + match "product" "(0x2200|0x3800)"; + action "kldload ng_ubt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0584"; + match "product" "0xb000"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0584"; + match "product" "0xb020"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0586"; + match "product" "(0x3401|0x3407|0x3409|0x340a|0x340f|0x3410)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0586"; + match "product" "(0x3416|0x341a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x058f"; + match "product" "0x9720"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05a6"; + match "product" "0x0101"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "(0x020d|0x020e|0x020f|0x0215|0x0217|0x0218|0x0219|0x021a|0x021b|0x021c|0x0229|0x022a|0x022b|0x030a|0x030b)"; + action "kldload atp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1402"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ad"; + match "product" "0x0fba"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05c6"; + match "product" "(0x6000|0x6613)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05cc"; + match "product" "0x3000"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05db"; + match "product" "(0x0003|0x0005|0x0009|0x000a|0x0011)"; + action "kldload uvscom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e0"; + match "product" "(0x2000|0x2001|0x2002|0x2003|0x2004|0x2005|0x2006|0x2007|0x2008|0x2009|0x200a)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e3"; + match "product" "0x0501"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e9"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x066b"; + match "product" "(0x200c|0x2202)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x066b"; + match "product" "0x2202"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x066b"; + match "product" "(0x2203|0x2204|0x2206|0x400b)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0675"; + match "product" "0x0550"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "(0x0000|0x0001)"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "(0x04bb|0x0609|0x0611|0x0612|0x1234|0x206a|0x2303)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "0x2501"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "(0x331a|0xaaa0|0xaaa2)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067c"; + match "product" "0x1001"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067e"; + match "product" "0x1001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0681"; + match "product" "0x3c06"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06e1"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06f8"; + match "product" "0xe000"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06f8"; + match "product" "(0xe010|0xe020)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06f8"; + match "product" "0xe030"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "0x0100"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "(0x0200|0x0201)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "0xee13"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "0xee13"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0711"; + match "product" "(0x0200|0x0210|0x0230)"; + action "kldload umct"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0731"; + match "product" "(0x0528|0x2003)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0745"; + match "product" "0x0001"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0745"; + match "product" "0x1000"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0769"; + match "product" "0x11f2"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0769"; + match "product" "0x11f3"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0769"; + match "product" "0x31f3"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x077b"; + match "product" "0x2226"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0789"; + match "product" "0x010c"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0789"; + match "product" "0x0160"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0789"; + match "product" "(0x0162|0x0163|0x0164)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x078b"; + match "product" "0x1234"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x079b"; + match "product" "0x0027"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x079b"; + match "product" "(0x004a|0x0062)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07a6"; + match "product" "(0x07c2|0x0986|0x8511|0x8513|0x8515)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x0001"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "(0x0004|0x000d)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x0017"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x002a"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "(0x002d|0x002e)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "(0x002f|0x003c|0x003f|0x0041|0x0042)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x9601"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0x110c|0x200c)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0x2770|0x2870|0x3070|0x3071|0x3072)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0x4000"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0x4002|0x4003|0x4004|0x4007|0x400b|0x400c|0x4102|0x4104)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0x420a"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0x6001"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0xabc1"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0xb21b|0xb21c|0xb21d|0xb21e|0xb21f)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07c9"; + match "product" "0xb100"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07cf"; + match "product" "(0x2001|0x2002|0x2003)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07d1"; + match "product" "0x3a0c"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07d1"; + match "product" "(0x3c03|0x3c04|0x3c06|0x3c07)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07d1"; + match "product" "(0x3c09|0x3c0a|0x3c0b|0x3c0d|0x3c0e|0x3c0f|0x3c11|0x3c13|0x3c15|0x3c16)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x081e"; + match "product" "0xdf00"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x082d"; + match "product" "(0x0100|0x0200|0x0300)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0830"; + match "product" "(0x0001|0x0002|0x0003|0x0020|0x0031|0x0040|0x0050|0x0060|0x0061|0x0070)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0833"; + match "product" "(0x012e|0x039f)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x1046"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4506"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4506"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4508"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4521"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x5046"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "(0x6618|0x7511|0x7512|0x7522|0x8522|0xa512|0xa618|0xa701|0xa702|0xb522|0xc522|0xd522)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0xe501"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0841"; + match "product" "0x0001"; + action "kldload urio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "(0x1001|0x1002)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x1020"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x1040"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x4240"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x4260"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x4300"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "(0x6100|0x6a00)"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0856"; + match "product" "0xac01"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x085a"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x086e"; + match "product" "0x1920"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x087d"; + match "product" "0x5704"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08d1"; + match "product" "0x0001"; + action "kldload if_cue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08d1"; + match "product" "0x0003"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08dd"; + match "product" "(0x0986|0x0987|0x0988|0x8511)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08dd"; + match "product" "0x90ff"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08e6"; + match "product" "0x5501"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08fd"; + match "product" "0x000a"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0915"; + match "product" "(0x2000|0x2002)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x091e"; + match "product" "0x0004"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0921"; + match "product" "0x1001"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0930"; + match "product" "(0x0700|0x0705|0x0706|0x0707|0x0708|0x0709|0x070a|0x070b)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0930"; + match "product" "0x0a07"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0930"; + match "product" "(0x0d45|0x1302)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x093c"; + match "product" "(0x0601|0x0701)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x094b"; + match "product" "0x0001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0951"; + match "product" "0x0008"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0951"; + match "product" "0x000a"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x095a"; + match "product" "0x3003"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0960"; + match "product" "(0x0065|0x0066|0x0067)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0961"; + match "product" "0x0010"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x099e"; + match "product" "(0x0052|0x4000)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x09aa"; + match "product" "0x1000"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x09d7"; + match "product" "0x0100"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0a46"; + match "product" "(0x0268|0x8515|0x9601)"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0a5c"; + match "product" "0x2033"; + action "kldload ubtbcmfw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0ace"; + match "product" "(0x1211|0x1215)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x5000|0x6000|0x6050|0x6100|0x6150|0x6200|0x6250|0x6300|0x6350|0x6500|0x6501|0x6600|0x6601|0x6701|0x6721|0x6741|0x6761|0x6800|0x6901)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x6911"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x6971"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x6971"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x7001"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x7011"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x7021|0x7041|0x7061|0x7100|0x7201|0x7211)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x7251|0x7301|0x7361|0x7381|0x7401|0x7501)"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x7601"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x7601|0xc031|0xd013|0xd031)"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0xd033"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0xd033|0xd055|0xd055)"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x1706|0x1707)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x170c|0x171b)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "0x171d"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x1723|0x1724)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x1731|0x1732|0x1742|0x1760|0x1761|0x1784|0x1790)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x4200|0x4201|0x4202|0x420f|0x9200|0x9202)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b39"; + match "product" "0x0109"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b39"; + match "product" "0x0421"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b3b"; + match "product" "(0x1630|0x5630|0x6630)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b41"; + match "product" "0x0011"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b63"; + match "product" "0x6530"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b8c"; + match "product" "0x2303"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b95"; + match "product" "(0x1720|0x1780|0x7720|0x772a)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0baf"; + match "product" "0x0118"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0baf"; + match "product" "0x0121"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bb2"; + match "product" "0x6098"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bb4"; + match "product" "(0x00ce|0x00cf|0x00cf|0x0a01|0x0a02|0x0a03|0x0a04|0x0a05|0x0a06|0x0a07|0x0a08|0x0a09|0x0a0a|0x0a0b|0x0a0c|0x0a0d|0x0a0e|0x0a0f|0x0a10|0x0a11|0x0a12|0x0a13|0x0a14|0x0a15|0x0a16|0x0a17|0x0a18|0x0a19|0x0a1a|0x0a1b|0x0a1c|0x0a1d|0x0a1e|0x0a1f|0x0a20|0x0a21|0x0a22|0x0a23|0x0a24|0x0a25|0x0a26|0x0a27|0x0a28|0x0a29|0x0a2a|0x0a2b|0x0a2c|0x0a2d|0x0a2e|0x0a2f|0x0a30|0x0a31|0x0a32|0x0a33|0x0a34|0x0a35|0x0a36|0x0a37|0x0a38|0x0a39|0x0a3a|0x0a3b|0x0a3c|0x0a3d|0x0a3e|0x0a3f|0x0a40|0x0a41|0x0a42|0x0a43|0x0a44|0x0a45|0x0a46|0x0a47|0x0a48|0x0a49|0x0a4a|0x0a4b|0x0a4c|0x0a4d|0x0a4e|0x0a4f|0x0a50|0x0a51|0x0a52|0x0a53|0x0a54|0x0a55|0x0a56|0x0a57|0x0a58|0x0a59|0x0a5a|0x0a5b|0x0a5c|0x0a5d|0x0a5e|0x0a5f|0x0a60|0x0a61|0x0a62|0x0a63|0x0a64|0x0a65|0x0a66|0x0a67|0x0a68|0x0a69|0x0a6a|0x0a6b|0x0a6c|0x0a6d|0x0a6e|0x0a6f|0x0a70|0x0a71|0x0a72|0x0a73|0x0a74|0x0a75|0x0a76|0x0a77|0x0a78|0x0a79|0x0a7a|0x0a7b|0x0a7c|0x0a7d|0x0a7e|0x0a7f|0x0a80|0x0a81|0x0a82|0x0a83|0x0a84|0x0a85|0x0a86|0x0a87|0x0a88|0x0a89|0x0a8a|0x0a8b|0x0a8c|0x0a8d|0x0a8e|0x0a8f|0x0a90|0x0a91|0x0a92|0x0a93|0x0a94|0x0a95|0x0a96|0x0a97|0x0a98|0x0a99|0x0a9a|0x0a9b|0x0a9c|0x0a9d|0x0a9e|0x0a9f|0x0bce)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bda"; + match "product" "0x8150"; + action "kldload if_rue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bda"; + match "product" "(0x8187|0x8189|0x8197|0x8198)"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bed"; + match "product" "(0x1100|0x1101)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bf8"; + match "product" "0x1001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bf8"; + match "product" "0x1009"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c44"; + match "product" "0x03a2"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c88"; + match "product" "0x17da"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c88"; + match "product" "0x17da"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c88"; + match "product" "0x180a"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c8e"; + match "product" "0x6000"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cad"; + match "product" "0x9001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0008"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0011"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0012"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0015"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x001a"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "(0x0022|0x0025)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cf3"; + match "product" "(0x0001|0x0003|0x0005)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0d8e"; + match "product" "0x3762"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0d8e"; + match "product" "(0x7801|0x7811)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x3820|0x3821|0x3822|0x3870|0x3871)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x6861|0x6865|0x6869)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x6874|0x6877)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x6899|0x821a|0x822a|0x870a|0x871a|0x899a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0xa861|0xa874)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db7"; + match "product" "0x0002"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x000d"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x0017"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x0021"; + action "kldload if_mos"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x0028"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "(0x002b|0x002c|0x002d|0x0039|0x003b|0x003c|0x003d|0x003e|0x003f|0x0040|0x0041|0x0042|0x0047|0x0048|0x004a|0x004d)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x061c"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "(0x9071|0x9075)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "(0x90ac|0x9712)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df7"; + match "product" "0x0620"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e0b"; + match "product" "(0x9031|0x9041)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e55"; + match "product" "0x110b"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e66"; + match "product" "(0x0001|0x0003|0x0009|0x000b)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e66"; + match "product" "0x400c"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e67"; + match "product" "0x0002"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e7e"; + match "product" "0x1001"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0ea0"; + match "product" "0x6858"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eab"; + match "product" "0xc893"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eb0"; + match "product" "0x9020"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eb0"; + match "product" "0x9021"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eba"; + match "product" "(0x1080|0x2080)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eef"; + match "product" "(0x0001|0x0002)"; + action "kldload uep"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f3d"; + match "product" "0x0112"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f3d"; + match "product" "0x0112"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f4e"; + match "product" "0x0200"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f88"; + match "product" "0x3012"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f88"; + match "product" "0x3014"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f94"; + match "product" "0x0001"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f98"; + match "product" "0x0201"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fb8"; + match "product" "(0x3001|0x3002|0x3003|0x4001)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fcf"; + match "product" "(0x1003|0x1004|0x1006)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fe6"; + match "product" "(0x8101|0x9700)"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x100d"; + match "product" "(0x9031|0x9032)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1011"; + match "product" "0x3198"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "0x8001"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "0x8002"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "0x8007"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "(0x8008|0x800a)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "(0x800b|0x800c|0x800d)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1066"; + match "product" "(0x00ce|0x0300|0x0500|0x0600|0x0700)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x106c"; + match "product" "0x3701"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10a6"; + match "product" "0xaa26"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10ab"; + match "product" "0x10c5"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10b5"; + match "product" "0xac70"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10b5"; + match "product" "0xac70"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10bd"; + match "product" "0x1427"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c4"; + match "product" "(0x0f91|0x1101|0x1601|0x800a|0x803b|0x8043|0x8044)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c4"; + match "product" "0x8053"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c4"; + match "product" "(0x8066|0x806f|0x807a|0x80ca|0x80dd|0x80ed|0x80f6|0x8115|0x813d|0x813f|0x814a|0x814a|0x814b|0x8156|0x815e|0x818b|0x819f|0x81a6|0x81ac|0x81ad|0x81c8|0x81e2|0x81e7|0x81e8|0x81f2|0x8218|0x822b|0x826b|0x8293|0x82f9|0x8341|0x8382|0x83a8|0x8411|0x846e|0x8477|0xea60|0xea61|0xea71|0xf001|0xf002|0xf003|0xf004)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c5"; + match "product" "0xea61"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10ce"; + match "product" "0xea61"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1114"; + match "product" "(0x0001|0x0004|0x0006)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x114b"; + match "product" "0x0110"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x114b"; + match "product" "0x0150"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1163"; + match "product" "0x0100"; + action "kldload ucycom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1182"; + match "product" "0x1388"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1186"; + match "product" "0x3e04"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1189"; + match "product" "0x0893"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1199"; + match "product" "(0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0112|0x0120|0x0218)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1199"; + match "product" "0x0218"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1199"; + match "product" "(0x0220|0x0224|0x0fff|0x6802|0x6803|0x6804|0x6805|0x6808|0x6809|0x6812|0x6813|0x6815|0x6816|0x6820|0x6821|0x6822|0x6832|0x6833|0x6834|0x6835|0x6838|0x6839|0x683a|0x683b|0x683c|0x683d|0x683e|0x6850|0x6851|0x6852|0x6853|0x6855|0x6856|0x6859|0x685a|0x6880|0x6890|0x6891|0x6892|0x6893|0x68a3)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11ad"; + match "product" "0x0701"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11d9"; + match "product" "(0x1002|0x1003)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f5"; + match "product" "(0x0001|0x0003|0x0004|0x0005)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f6"; + match "product" "0x2001"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f7"; + match "product" "0x02df"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1231"; + match "product" "(0xce01|0xce02)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x126f"; + match "product" "0xa006"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x129b"; + match "product" "0x1666"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x129b"; + match "product" "0x1828"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1465|0x14ac|0x1520)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12ef"; + match "product" "0x0100"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1342"; + match "product" "0x0204"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1371"; + match "product" "(0x9022|0x9032)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1371"; + match "product" "0x9401"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1385"; + match "product" "(0x4250|0x5f00|0x5f02)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13ad"; + match "product" "0x9999"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x000c"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "(0x000d|0x0011)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x0018"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x001a"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "(0x0020|0x0023)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x0024"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13d2"; + match "product" "0x0400"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13d3"; + match "product" "(0x3247|0x3262|0x3273|0x3284|0x3305)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1410"; + match "product" "(0x1100|0x1110|0x1120|0x1130|0x1400|0x1410|0x1420|0x1430|0x1450|0x2100|0x2110|0x2120|0x2130|0x2400|0x2410|0x2420|0x4100|0x4400|0x5010|0x5100|0x6000|0x6002|0x7042)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1416"; + match "product" "0x1110"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1435"; + match "product" "0x0427"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1435"; + match "product" "0x0711"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1435"; + match "product" "(0x0826|0x082a)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1453"; + match "product" "0x4026"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1472"; + match "product" "0x0009"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1482"; + match "product" "0x3c09"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1485"; + match "product" "(0x0001|0x0002)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x1706"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x2070"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x2570"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "(0x2573|0x2671)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "(0x2770|0x2870|0x3070|0x3071|0x3072|0x3370|0x3572|0x8070)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x9020"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x9021"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "0x3c02"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "(0x3c06|0x3c07|0x3c08|0x3c09|0x3c11|0x3c12)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "0x3c22"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "(0x3c23|0x3c25|0x3c25|0x3c27|0x3c28)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14ea"; + match "product" "0xab10"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14ea"; + match "product" "0xab11"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14ea"; + match "product" "0xab13"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1555"; + match "product" "0x0004"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1557"; + match "product" "0x7720"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1557"; + match "product" "0x8150"; + action "kldload if_rue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x3006"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "(0x300a|0x300b|0x300d)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x300e"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x3204"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x3205"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1582"; + match "product" "0x6003"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15a9"; + match "product" "0x0004"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15a9"; + match "product" "(0x0006|0x0010)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15c5"; + match "product" "0x0008"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15e8"; + match "product" "(0x9100|0x9110)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1614"; + match "product" "(0x0800|0x0802|0x7002)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1631"; + match "product" "0x6200"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1631"; + match "product" "0xc019"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1645"; + match "product" "(0x0005|0x0008|0x8005)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x166a"; + match "product" "0x0303"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x167b"; + match "product" "0x4001"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x168c"; + match "product" "0x0001"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "0x0601"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "(0x0710|0x0712)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "0x0722"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "(0x0740|0x0744)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16ab"; + match "product" "(0x7801|0x7811)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "(0x6202|0x6501)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "0x6501"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "0x6502"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "0x6502"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d6"; + match "product" "(0x0001|0x0001)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d8"; + match "product" "(0x6006|0x6280)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d8"; + match "product" "0x6280"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16dc"; + match "product" "(0x0010|0x0011|0x0012|0x0015)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1726"; + match "product" "0x1000"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1726"; + match "product" "0x1000"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "0x0039"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "(0x0070|0x0071)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "0x0073"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "(0x0077|0x0078|0x0079)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1740"; + match "product" "(0x0605|0x0615)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1740"; + match "product" "0x2000"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1740"; + match "product" "(0x9701|0x9702|0x9703|0x9705|0x9706|0x9707|0x9708|0x9709|0x9801)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1761"; + match "product" "0x0b05"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x177f"; + match "product" "(0x0153|0x0302|0x0313)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x17f4"; + match "product" "0xaaaa"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1843"; + match "product" "0x0200"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18c5"; + match "product" "0x0002"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18c5"; + match "product" "(0x0008|0x0012)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "(0x6196|0x6229)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "0x6232"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "0x6238"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "0x6259"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18ef"; + match "product" "0xe00f"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x19d2"; + match "product" "(0x0001|0x0002|0x0003|0x0004|0x0005|0x0006|0x0007|0x0008|0x0009|0x000a|0x000b|0x000c|0x000d|0x000e|0x000f|0x0010|0x0011|0x0012|0x0013|0x0014|0x0015|0x0016|0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0030|0x0031|0x0032|0x0033|0x0037|0x0039|0x0042|0x0043|0x0048|0x0049|0x0051|0x0052|0x0053|0x0054|0x0055|0x0057|0x0058|0x0059|0x0060|0x0061|0x0062|0x0063|0x0064|0x0066|0x0069|0x0070|0x0073|0x0076|0x0078|0x0082|0x0086|0x0117|0x2000|0x2002|0x2003|0xfff1|0xfff5|0xfffe)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1a86"; + match "product" "0x7523"; + action "kldload uchcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1a8d"; + match "product" "(0x1002|0x1003|0x1004|0x1005|0x1006|0x1007|0x1008|0x1009|0x100a|0x100b|0x100c|0x100d|0x100e|0x100f|0x1010|0x1011|0x1012)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b3d"; + match "product" "0x0153"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b75"; + match "product" "0x3072"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b75"; + match "product" "0x8187"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1bbb"; + match "product" "(0x0000|0xf000)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1bc7"; + match "product" "(0x1003|0x1004)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1be3"; + match "product" "0x07a6"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1c9e"; + match "product" "(0x6061|0x9603|0xf000)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1cf1"; + match "product" "(0x0001|0x0004)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1d09"; + match "product" "0x4000"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1d4d"; + match "product" "(0x0002|0x000c|0x000e|0x0010)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1da5"; + match "product" "(0x4512|0x4515|0x4519|0x4523)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1e0e"; + match "product" "(0x9000|0x9200|0xce16)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1eda"; + match "product" "0x2310"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x1a00"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x200c"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "(0x3a00|0x3a02|0x3a04)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x3c00"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x3c05"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "(0x3c09|0x3c0a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x4000"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "(0x4001|0x4002|0x4003|0x400b|0x4102|0xabc1)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0x5303"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0xab01"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "(0xab24|0xab25)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0xab50"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "(0xc007|0xed01)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0xed02"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "(0xed06|0xed14)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x203d"; + match "product" "(0x1480|0x14a1|0x14a9)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20b8"; + match "product" "0x8888"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20b9"; + match "product" "0x1682"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x22b8"; + match "product" "(0x4204|0x4214|0x4224|0x4234|0x4244)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x22b8"; + match "product" "(0x600c|0x6027)"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2478"; + match "product" "0x2008"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3334"; + match "product" "0x1701"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3340"; + match "product" "(0x011c|0x0326|0x0426|0x043a|0x051c|0x053a|0x071c|0x0b1c|0x0e3a|0x0f1c|0x0f3a|0x1326|0x191c|0x2326|0x3326)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3708"; + match "product" "(0x20ce|0x21ce)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4113"; + match "product" "(0x0210|0x0211|0x0400|0x0410)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "(0x4001|0x4002|0x4003|0x4004|0x4005|0x4006|0x4007|0x4008|0x4009)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "(0x8102|0x8104)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "(0x8114|0x8115|0x8116|0x8117|0x8118|0x8128|0x8129|0x8133|0x8134|0x8135|0x8136|0x8137|0x8138|0x8180|0x8181|0x8182)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "0x9500"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4348"; + match "product" "0x5523"; + action "kldload uchcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4505"; + match "product" "0x0010"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4766"; + match "product" "0x0001"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5173"; + match "product" "0x1809"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5372"; + match "product" "0x2303"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5a57"; + match "product" "0x0260"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5a57"; + match "product" "(0x0280|0x0282|0x0283|0x0284|0x5257)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5e04"; + match "product" "0xce00"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6189"; + match "product" "0x182d"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6189"; + match "product" "0x2068"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6547"; + match "product" "0x0232"; + action "kldload uark"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6891"; + match "product" "0xa727"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x7392"; + match "product" "0x7318"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x7392"; + match "product" "(0x7711|0x7717|0x7718)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x8516"; + match "product" "(0x2070|0x2770|0x2870|0x3070|0x3071|0x3072|0x3572)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7703"; + action "kldload umoscom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7730"; + action "kldload if_mos"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7820"; + action "kldload umcs"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7830"; + action "kldload if_mos"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7840"; + action "kldload umcs"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9e88"; + match "product" "0x9e8f"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0xdaae"; + match "product" "0xead6"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x02"; + match "intprotocol" "0x01"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ukbd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + match "intsubclass" "0x01"; + match "intprotocol" "0x02"; + action "kldload ums"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x02"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x03"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0xe0"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ng_ubt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0xff"; + match "intsubclass" "0x5d"; + match "intprotocol" "0x01"; + action "kldload uhid"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x01"; + match "intsubclass" "0x01"; + action "kldload snd_uaudio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x01"; + match "intsubclass" "0x03"; + action "kldload snd_uaudio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x06"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x0a"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x0d"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x88"; + action "kldload ufoma"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + action "kldload uhid"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x08"; + action "kldload umass"; +}; + +# 1634 USB entries processed + diff --git a/etc/devd/bus_auto.conf b/etc/devd/bus_auto.conf deleted file mode 100644 index a1c7236..0000000 --- a/etc/devd/bus_auto.conf +++ /dev/null @@ -1,2381 +0,0 @@ -# -# $FreeBSD$ -# -# This file was automatically generated by "tools/bus_autoconf.sh". -# Please do not edit! -# - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "(host|device)"; - match "intclass" "0x02"; - match "intsubclass" "0x06"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "(host|device)"; - match "intclass" "0x02"; - match "intsubclass" "0x0a"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "(host|device)"; - match "intclass" "0x02"; - match "intsubclass" "0x0d"; - action "kldload if_cdce"; -}; - -# 3 usb_dual entries processed - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1290"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1292"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1294"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1297"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0104"; - match "product" "0x00be"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0123"; - match "product" "0x0001"; - action "kldload uep"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03e8"; - match "product" "0x0008"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03eb"; - match "product" "0x2109"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "(0x0121|0x1016|0x1116|0x1216|0x1b1d|0x1e1d|0x2016|0x2116|0x2216|0x3016|0x3116|0x3216|0x3524|0x4016|0x4116|0x4216|0x5016|0x5116|0x5216|0x811c|0xca02)"; - action "kldload ugensa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0402"; - match "product" "0x5632"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0403"; - match "product" "(0x6001|0x6004|0x6010|0x6011|0x8372|0x9e90|0xcc48|0xcc49|0xcc4a|0xd678|0xe6c8|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xee18|0xf608|0xf60b|0xf850|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfc08|0xfc09|0xfc0b|0xfc0c|0xfc0d|0xfc82)"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0408"; - match "product" "(0x0304|0x1000|0xea02|0xea03|0xea04|0xea05|0xea06)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0409"; - match "product" "(0x00d5|0x00d6|0x00d7|0x8024|0x8025)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "(0x0001|0x0005|0x0009|0x0012|0x003d|0x005e|0x0066|0x0067|0x006e|0x008b|0x00b3|0x00d8|0x00d9|0x00da|0x00e8|0x0116|0x0119|0x012e|0x0137|0x0148|0x0150|0x015d|0x016f)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0413"; - match "product" "0x2101"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0423"; - match "product" "(0x000a|0x000c)"; - action "kldload if_cue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x043e"; - match "product" "0x9c01"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045a"; - match "product" "(0x5001|0x5002)"; - action "kldload urio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045b"; - match "product" "0x0053"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045e"; - match "product" "(0x0079|0x007a|0x00ce|0x0400|0x0401|0x0402|0x0403|0x0404|0x0405|0x0406|0x0407|0x0408|0x0409|0x040a|0x040b|0x040c|0x040d|0x040e|0x040f|0x0410|0x0411|0x0412|0x0413|0x0414|0x0415|0x0416|0x0417|0x0432|0x0433|0x0434|0x0435|0x0436|0x0437|0x0438|0x0439|0x043a|0x043b|0x043c|0x043d|0x043e|0x043f|0x0440|0x0441|0x0442|0x0443|0x0444|0x0445|0x0446|0x0447|0x0448|0x0449|0x044a|0x044b|0x044c|0x044d|0x044e|0x044f|0x0450|0x0451|0x0452|0x0453|0x0454|0x0455|0x0456|0x0457|0x0458|0x0459|0x045a|0x045b|0x045c|0x045d|0x045e|0x045f|0x0460|0x0461|0x0462|0x0463|0x0464|0x0465|0x0466|0x0467|0x0468|0x0469|0x046a|0x046b|0x046c|0x046d|0x046e|0x046f|0x0470|0x0471|0x0472|0x0473|0x0474|0x0475|0x0476|0x0477|0x0478|0x0479|0x047a|0x047b|0x04c8|0x04c9|0x04ca|0x04cb|0x04cc|0x04cd|0x04ce|0x04d7|0x04d8|0x04d9|0x04da|0x04db|0x04dc|0x04dd|0x04de|0x04df|0x04e0|0x04e1|0x04e2|0x04e3|0x04e4|0x04e5|0x04e6|0x04e7|0x04e8|0x04e9|0x04ea)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0471"; - match "product" "(0x066a|0x1236|0x200f)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0482"; - match "product" "0x0203"; - action "kldload umodem"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0489"; - match "product" "(0xe000|0xe003)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x049f"; - match "product" "(0x0003|0x0032|0x505a)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04a4"; - match "product" "0x0014"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04a5"; - match "product" "(0x4027|0x4068)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04ad"; - match "product" "(0x0301|0x0302|0x0303|0x0306)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04b4"; - match "product" "0x1002"; - action "kldload ufm"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04b7"; - match "product" "0x0531"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04b8"; - match "product" "(0x0521|0x0522)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bb"; - match "product" "(0x0901|0x0904|0x0913|0x0930|0x0944|0x0945|0x0947|0x0948|0x0a03|0x0a0e)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bf"; - match "product" "(0x0115|0x0117)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04c5"; - match "product" "(0x1058|0x1079)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04da"; - match "product" "(0x2500|0x3900)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04dd"; - match "product" "(0x8004|0x8005|0x8006|0x8007|0x9031|0x9102|0x9121|0x9123|0x9151|0x91ac|0x9242)"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04e8"; - match "product" "(0x5f00|0x5f01|0x5f02|0x5f03|0x5f04|0x6601|0x6611|0x6613|0x6615|0x6617|0x6619|0x661b|0x662e|0x6630|0x6632|0x8001)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04f1"; - match "product" "(0x3008|0x3011|0x3012)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0502"; - match "product" "(0x1631|0x1632|0x16e1|0x16e2|0x16e3)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0506"; - match "product" "(0x03e8|0x11f8|0x4601)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "(0x0103|0x0109|0x0121|0x0257|0x0409|0x1203|0x4050|0x5055|0x7050|0x7050|0x7051|0x705a|0x705c|0x705e|0x8053|0x805c|0x815c|0x825a|0x905b|0x935a)"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0525"; - match "product" "(0x1080|0xa4a2)"; - action "kldload udbp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0536"; - match "product" "0x01a0"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0543"; - match "product" "(0x0ed9|0x1527|0x1529|0x152b|0x152e|0x1921|0x1922|0x1923)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0547"; - match "product" "(0x2008|0x2720)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x054c"; - match "product" "(0x0038|0x0066|0x0095|0x009a|0x00da|0x0169|0x0437)"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0557"; - match "product" "(0x2002|0x2007|0x2008|0x2009|0x4000)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x055d"; - match "product" "0x2018"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0565"; - match "product" "(0x0001|0x0002|0x0003|0x0005)"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0567"; - match "product" "(0x2000|0x2002)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x056c"; - match "product" "0x8007"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x056e"; - match "product" "(0x200c|0x4002|0x4005|0x400b|0x4010|0x5003|0x5004|0xabc1)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x057c"; - match "product" "(0x2200|0x3800)"; - action "kldload ng_ubt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0584"; - match "product" "(0xb000|0xb020)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0586"; - match "product" "(0x3401|0x3407|0x3409|0x340a|0x340f|0x3410|0x3416|0x341a)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x058f"; - match "product" "0x9720"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05a6"; - match "product" "0x0101"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "(0x020d|0x020e|0x020f|0x0215|0x0217|0x0218|0x0219|0x021a|0x021b|0x021c|0x0229|0x022a|0x022b|0x030a|0x030b|0x1402)"; - action "kldload atp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ad"; - match "product" "0x0fba"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05c6"; - match "product" "(0x6000|0x6613)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05cc"; - match "product" "0x3000"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05db"; - match "product" "(0x0003|0x0005|0x0009|0x000a|0x0011)"; - action "kldload uvscom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05e0"; - match "product" "(0x2000|0x2001|0x2002|0x2003|0x2004|0x2005|0x2006|0x2007|0x2008|0x2009|0x200a)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05e3"; - match "product" "0x0501"; - action "kldload udbp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05e9"; - match "product" "(0x0008|0x0009)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x066b"; - match "product" "(0x200c|0x2202|0x2202|0x2203|0x2204|0x2206|0x400b)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0675"; - match "product" "0x0550"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067b"; - match "product" "(0x0000|0x0001|0x04bb|0x0609|0x0611|0x0612|0x1234|0x206a|0x2303|0x2501|0x331a|0xaaa0|0xaaa2)"; - action "kldload udbp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067c"; - match "product" "0x1001"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067e"; - match "product" "0x1001"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0681"; - match "product" "0x3c06"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x06e1"; - match "product" "(0x0008|0x0009)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x06f8"; - match "product" "(0xe000|0xe010|0xe020|0xe030)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0707"; - match "product" "(0x0100|0x0200|0x0201|0xee13|0xee13)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0711"; - match "product" "(0x0200|0x0210|0x0230)"; - action "kldload umct"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0731"; - match "product" "(0x0528|0x2003)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0745"; - match "product" "(0x0001|0x1000)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0769"; - match "product" "(0x11f2|0x11f3|0x31f3)"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x077b"; - match "product" "0x2226"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0789"; - match "product" "(0x010c|0x0160|0x0162|0x0163|0x0164)"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x078b"; - match "product" "0x1234"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x079b"; - match "product" "(0x0027|0x004a|0x0062)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07a6"; - match "product" "(0x07c2|0x0986|0x8511|0x8513|0x8515)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "(0x0001|0x0004|0x000d|0x0017|0x002a|0x002d|0x002e|0x002f|0x003c|0x003f|0x0041|0x0042|0x9601)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "(0x110c|0x200c|0x2770|0x2870|0x3070|0x3071|0x3072|0x4000|0x4002|0x4003|0x4004|0x4007|0x400b|0x400c|0x4102|0x4104|0x420a|0x6001|0xabc1|0xb21b|0xb21c|0xb21d|0xb21e|0xb21f)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07c9"; - match "product" "0xb100"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07cf"; - match "product" "(0x2001|0x2002|0x2003)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07d1"; - match "product" "(0x3a0c|0x3c03|0x3c04|0x3c06|0x3c07|0x3c09|0x3c0a|0x3c0b|0x3c0d|0x3c0e|0x3c0f|0x3c11|0x3c13|0x3c15|0x3c16)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x081e"; - match "product" "0xdf00"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x082d"; - match "product" "(0x0100|0x0200|0x0300)"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0830"; - match "product" "(0x0001|0x0002|0x0003|0x0020|0x0031|0x0040|0x0050|0x0060|0x0061|0x0070)"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0833"; - match "product" "(0x012e|0x039f)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "(0x1046|0x4506|0x4506|0x4508|0x4521|0x5046|0x6618|0x7511|0x7512|0x7522|0x8522|0xa512|0xa618|0xa701|0xa702|0xb522|0xc522|0xd522|0xe501)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0841"; - match "product" "0x0001"; - action "kldload urio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "(0x1001|0x1002|0x1020|0x1040|0x4240|0x4260|0x4300|0x6100|0x6a00)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0856"; - match "product" "0xac01"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x085a"; - match "product" "(0x0008|0x0009)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x086e"; - match "product" "0x1920"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x087d"; - match "product" "0x5704"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08d1"; - match "product" "(0x0001|0x0003)"; - action "kldload if_cue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08dd"; - match "product" "(0x0986|0x0987|0x0988|0x8511|0x90ff)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08e6"; - match "product" "0x5501"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08fd"; - match "product" "0x000a"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0915"; - match "product" "(0x2000|0x2002)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x091e"; - match "product" "0x0004"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0921"; - match "product" "0x1001"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0930"; - match "product" "(0x0700|0x0705|0x0706|0x0707|0x0708|0x0709|0x070a|0x070b|0x0a07|0x0d45|0x1302)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x093c"; - match "product" "(0x0601|0x0701)"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x094b"; - match "product" "0x0001"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0951"; - match "product" "(0x0008|0x000a)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x095a"; - match "product" "0x3003"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0960"; - match "product" "(0x0065|0x0066|0x0067)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0961"; - match "product" "0x0010"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x099e"; - match "product" "(0x0052|0x4000)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x09aa"; - match "product" "0x1000"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x09d7"; - match "product" "0x0100"; - action "kldload ugensa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0a46"; - match "product" "(0x0268|0x8515|0x9601)"; - action "kldload if_udav"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0a5c"; - match "product" "0x2033"; - action "kldload ubtbcmfw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0ace"; - match "product" "(0x1211|0x1215)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "(0x5000|0x6000|0x6050|0x6100|0x6150|0x6200|0x6250|0x6300|0x6350|0x6500|0x6501|0x6600|0x6601|0x6701|0x6721|0x6741|0x6761|0x6800|0x6901|0x6911|0x6971|0x6971|0x7001|0x7011|0x7021|0x7041|0x7061|0x7100|0x7201|0x7211|0x7251|0x7301|0x7361|0x7381|0x7401|0x7501|0x7601|0x7601|0xc031|0xd013|0xd031|0xd033|0xd033|0xd055|0xd055)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b05"; - match "product" "(0x1706|0x1707|0x170c|0x171b|0x171d|0x1723|0x1724|0x1731|0x1732|0x1742|0x1760|0x1761|0x1784|0x1790|0x4200|0x4201|0x4202|0x420f|0x9200|0x9202)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b39"; - match "product" "(0x0109|0x0421)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b3b"; - match "product" "(0x1630|0x5630|0x6630)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b41"; - match "product" "0x0011"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b63"; - match "product" "0x6530"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b8c"; - match "product" "0x2303"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b95"; - match "product" "(0x1720|0x1780|0x7720|0x772a)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0baf"; - match "product" "(0x0118|0x0121)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bb2"; - match "product" "0x6098"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bb4"; - match "product" "(0x00ce|0x00cf|0x00cf|0x0a01|0x0a02|0x0a03|0x0a04|0x0a05|0x0a06|0x0a07|0x0a08|0x0a09|0x0a0a|0x0a0b|0x0a0c|0x0a0d|0x0a0e|0x0a0f|0x0a10|0x0a11|0x0a12|0x0a13|0x0a14|0x0a15|0x0a16|0x0a17|0x0a18|0x0a19|0x0a1a|0x0a1b|0x0a1c|0x0a1d|0x0a1e|0x0a1f|0x0a20|0x0a21|0x0a22|0x0a23|0x0a24|0x0a25|0x0a26|0x0a27|0x0a28|0x0a29|0x0a2a|0x0a2b|0x0a2c|0x0a2d|0x0a2e|0x0a2f|0x0a30|0x0a31|0x0a32|0x0a33|0x0a34|0x0a35|0x0a36|0x0a37|0x0a38|0x0a39|0x0a3a|0x0a3b|0x0a3c|0x0a3d|0x0a3e|0x0a3f|0x0a40|0x0a41|0x0a42|0x0a43|0x0a44|0x0a45|0x0a46|0x0a47|0x0a48|0x0a49|0x0a4a|0x0a4b|0x0a4c|0x0a4d|0x0a4e|0x0a4f|0x0a50|0x0a51|0x0a52|0x0a53|0x0a54|0x0a55|0x0a56|0x0a57|0x0a58|0x0a59|0x0a5a|0x0a5b|0x0a5c|0x0a5d|0x0a5e|0x0a5f|0x0a60|0x0a61|0x0a62|0x0a63|0x0a64|0x0a65|0x0a66|0x0a67|0x0a68|0x0a69|0x0a6a|0x0a6b|0x0a6c|0x0a6d|0x0a6e|0x0a6f|0x0a70|0x0a71|0x0a72|0x0a73|0x0a74|0x0a75|0x0a76|0x0a77|0x0a78|0x0a79|0x0a7a|0x0a7b|0x0a7c|0x0a7d|0x0a7e|0x0a7f|0x0a80|0x0a81|0x0a82|0x0a83|0x0a84|0x0a85|0x0a86|0x0a87|0x0a88|0x0a89|0x0a8a|0x0a8b|0x0a8c|0x0a8d|0x0a8e|0x0a8f|0x0a90|0x0a91|0x0a92|0x0a93|0x0a94|0x0a95|0x0a96|0x0a97|0x0a98|0x0a99|0x0a9a|0x0a9b|0x0a9c|0x0a9d|0x0a9e|0x0a9f|0x0bce)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bda"; - match "product" "(0x8150|0x8187|0x8189|0x8197|0x8198)"; - action "kldload if_rue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bed"; - match "product" "(0x1100|0x1101)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bf8"; - match "product" "(0x1001|0x1009)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c44"; - match "product" "0x03a2"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c88"; - match "product" "(0x17da|0x17da|0x180a)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c8e"; - match "product" "0x6000"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cad"; - match "product" "0x9001"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cde"; - match "product" "(0x0008|0x0011|0x0012|0x0015|0x001a|0x0022|0x0025)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cf3"; - match "product" "(0x0001|0x0003|0x0005)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0d8e"; - match "product" "(0x3762|0x7801|0x7811)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db0"; - match "product" "(0x3820|0x3821|0x3822|0x3870|0x3871|0x6861|0x6865|0x6869|0x6874|0x6877|0x6899|0x821a|0x822a|0x870a|0x871a|0x899a|0xa861|0xa874)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db7"; - match "product" "0x0002"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "(0x000d|0x0017|0x0021|0x0028|0x002b|0x002c|0x002d|0x0039|0x003b|0x003c|0x003d|0x003e|0x003f|0x0040|0x0041|0x0042|0x0047|0x0048|0x004a|0x004d|0x061c|0x9071|0x9075|0x90ac|0x9712)"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df7"; - match "product" "0x0620"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e0b"; - match "product" "(0x9031|0x9041)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e55"; - match "product" "0x110b"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e66"; - match "product" "(0x0001|0x0003|0x0009|0x000b|0x400c)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e67"; - match "product" "0x0002"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e7e"; - match "product" "0x1001"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0ea0"; - match "product" "0x6858"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eab"; - match "product" "0xc893"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eb0"; - match "product" "(0x9020|0x9021)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eba"; - match "product" "(0x1080|0x2080)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eef"; - match "product" "(0x0001|0x0002)"; - action "kldload uep"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f3d"; - match "product" "(0x0112|0x0112)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f4e"; - match "product" "0x0200"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f88"; - match "product" "(0x3012|0x3014)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f94"; - match "product" "0x0001"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f98"; - match "product" "0x0201"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0fb8"; - match "product" "(0x3001|0x3002|0x3003|0x4001)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0fcf"; - match "product" "(0x1003|0x1004|0x1006)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0fe6"; - match "product" "(0x8101|0x9700)"; - action "kldload if_udav"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x100d"; - match "product" "(0x9031|0x9032)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1011"; - match "product" "0x3198"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1044"; - match "product" "(0x8001|0x8002|0x8007|0x8008|0x800a|0x800b|0x800c|0x800d)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1066"; - match "product" "(0x00ce|0x0300|0x0500|0x0600|0x0700)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x106c"; - match "product" "0x3701"; - action "kldload umodem"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10a6"; - match "product" "0xaa26"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10ab"; - match "product" "0x10c5"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10b5"; - match "product" "(0xac70|0xac70)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10bd"; - match "product" "0x1427"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10c4"; - match "product" "(0x0f91|0x1101|0x1601|0x800a|0x803b|0x8043|0x8044|0x8053|0x8066|0x806f|0x807a|0x80ca|0x80dd|0x80ed|0x80f6|0x8115|0x813d|0x813f|0x814a|0x814a|0x814b|0x8156|0x815e|0x818b|0x819f|0x81a6|0x81ac|0x81ad|0x81c8|0x81e2|0x81e7|0x81e8|0x81f2|0x8218|0x822b|0x826b|0x8293|0x82f9|0x8341|0x8382|0x83a8|0x8411|0x846e|0x8477|0xea60|0xea61|0xea71|0xf001|0xf002|0xf003|0xf004)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10c5"; - match "product" "0xea61"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10ce"; - match "product" "0xea61"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1114"; - match "product" "(0x0001|0x0004|0x0006)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x114b"; - match "product" "(0x0110|0x0150)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1163"; - match "product" "0x0100"; - action "kldload ucycom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1182"; - match "product" "0x1388"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1186"; - match "product" "0x3e04"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1189"; - match "product" "0x0893"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1199"; - match "product" "(0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0112|0x0120|0x0218|0x0218|0x0220|0x0224|0x0fff|0x6802|0x6803|0x6804|0x6805|0x6808|0x6809|0x6812|0x6813|0x6815|0x6816|0x6820|0x6821|0x6822|0x6832|0x6833|0x6834|0x6835|0x6838|0x6839|0x683a|0x683b|0x683c|0x683d|0x683e|0x6850|0x6851|0x6852|0x6853|0x6855|0x6856|0x6859|0x685a|0x6880|0x6890|0x6891|0x6892|0x6893|0x68a3)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11ad"; - match "product" "0x0701"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11d9"; - match "product" "(0x1002|0x1003)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11f5"; - match "product" "(0x0001|0x0003|0x0004|0x0005)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11f6"; - match "product" "0x2001"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11f7"; - match "product" "0x02df"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1231"; - match "product" "(0xce01|0xce02)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x126f"; - match "product" "0xa006"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x129b"; - match "product" "(0x1666|0x1828)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x12d1"; - match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1465|0x14ac|0x1520)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x12ef"; - match "product" "0x0100"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1342"; - match "product" "0x0204"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1371"; - match "product" "(0x9022|0x9032|0x9401)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1385"; - match "product" "(0x4250|0x5f00|0x5f02)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13ad"; - match "product" "0x9999"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13b1"; - match "product" "(0x000c|0x000d|0x0011|0x0018|0x001a|0x0020|0x0023|0x0024)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13d2"; - match "product" "0x0400"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13d3"; - match "product" "(0x3247|0x3262|0x3273|0x3284|0x3305)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1410"; - match "product" "(0x1100|0x1110|0x1120|0x1130|0x1400|0x1410|0x1420|0x1430|0x1450|0x2100|0x2110|0x2120|0x2130|0x2400|0x2410|0x2420|0x4100|0x4400|0x5010|0x5100|0x6000|0x6002|0x7042)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1416"; - match "product" "0x1110"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1435"; - match "product" "(0x0427|0x0711|0x0826|0x082a)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1453"; - match "product" "0x4026"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1472"; - match "product" "0x0009"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1482"; - match "product" "0x3c09"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1485"; - match "product" "(0x0001|0x0002)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "(0x1706|0x2070|0x2570|0x2573|0x2671|0x2770|0x2870|0x3070|0x3071|0x3072|0x3370|0x3572|0x8070|0x9020|0x9021)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14b2"; - match "product" "(0x3c02|0x3c06|0x3c07|0x3c08|0x3c09|0x3c11|0x3c12|0x3c22|0x3c23|0x3c25|0x3c25|0x3c27|0x3c28)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14ea"; - match "product" "(0xab10|0xab11|0xab13)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1555"; - match "product" "0x0004"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1557"; - match "product" "(0x7720|0x8150)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x157e"; - match "product" "(0x3006|0x300a|0x300b|0x300d|0x300e|0x3204|0x3205)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1582"; - match "product" "0x6003"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x15a9"; - match "product" "(0x0004|0x0006|0x0010)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x15c5"; - match "product" "0x0008"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x15e8"; - match "product" "(0x9100|0x9110)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1614"; - match "product" "(0x0800|0x0802|0x7002)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1631"; - match "product" "(0x6200|0xc019)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1645"; - match "product" "(0x0005|0x0008|0x8005)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x166a"; - match "product" "0x0303"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x167b"; - match "product" "0x4001"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x168c"; - match "product" "0x0001"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1690"; - match "product" "(0x0601|0x0710|0x0712|0x0722|0x0740|0x0744)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16ab"; - match "product" "(0x7801|0x7811)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d5"; - match "product" "(0x6202|0x6501|0x6501|0x6502|0x6502)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d6"; - match "product" "(0x0001|0x0001)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d8"; - match "product" "(0x6006|0x6280|0x6280)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16dc"; - match "product" "(0x0010|0x0011|0x0012|0x0015)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1726"; - match "product" "(0x1000|0x1000)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1737"; - match "product" "(0x0039|0x0070|0x0071|0x0073|0x0077|0x0078|0x0079)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1740"; - match "product" "(0x0605|0x0615|0x2000|0x9701|0x9702|0x9703|0x9705|0x9706|0x9707|0x9708|0x9709|0x9801)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1761"; - match "product" "0x0b05"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x177f"; - match "product" "(0x0153|0x0302|0x0313)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x17f4"; - match "product" "0xaaaa"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1843"; - match "product" "0x0200"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18c5"; - match "product" "(0x0002|0x0008|0x0012)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18e8"; - match "product" "(0x6196|0x6229|0x6232|0x6238|0x6259)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18ef"; - match "product" "0xe00f"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x19d2"; - match "product" "(0x0001|0x0002|0x0003|0x0004|0x0005|0x0006|0x0007|0x0008|0x0009|0x000a|0x000b|0x000c|0x000d|0x000e|0x000f|0x0010|0x0011|0x0012|0x0013|0x0014|0x0015|0x0016|0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0030|0x0031|0x0032|0x0033|0x0037|0x0039|0x0042|0x0043|0x0048|0x0049|0x0051|0x0052|0x0053|0x0054|0x0055|0x0057|0x0058|0x0059|0x0060|0x0061|0x0062|0x0063|0x0064|0x0066|0x0069|0x0070|0x0073|0x0076|0x0078|0x0082|0x0086|0x0117|0x2000|0x2002|0x2003|0xfff1|0xfff5|0xfffe)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1a86"; - match "product" "0x7523"; - action "kldload uchcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1a8d"; - match "product" "(0x1002|0x1003|0x1004|0x1005|0x1006|0x1007|0x1008|0x1009|0x100a|0x100b|0x100c|0x100d|0x100e|0x100f|0x1010|0x1011|0x1012)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1b3d"; - match "product" "0x0153"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1b75"; - match "product" "(0x3072|0x8187)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1bbb"; - match "product" "(0x0000|0xf000)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1bc7"; - match "product" "(0x1003|0x1004)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1be3"; - match "product" "0x07a6"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1c9e"; - match "product" "(0x6061|0x9603|0xf000)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1cf1"; - match "product" "(0x0001|0x0004)"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1d09"; - match "product" "0x4000"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1d4d"; - match "product" "(0x0002|0x000c|0x000e|0x0010)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1da5"; - match "product" "(0x4512|0x4515|0x4519|0x4523)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1e0e"; - match "product" "(0x9000|0x9200|0xce16)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1eda"; - match "product" "0x2310"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "(0x1a00|0x200c|0x3a00|0x3a02|0x3a04|0x3c00|0x3c05|0x3c09|0x3c0a|0x4000|0x4001|0x4002|0x4003|0x400b|0x4102|0xabc1)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "(0x5303|0xab01|0xab24|0xab25|0xab50|0xc007|0xed01|0xed02|0xed06|0xed14)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x203d"; - match "product" "(0x1480|0x14a1|0x14a9)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x20b8"; - match "product" "0x8888"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x20b9"; - match "product" "0x1682"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x22b8"; - match "product" "(0x4204|0x4214|0x4224|0x4234|0x4244|0x600c|0x6027)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2478"; - match "product" "0x2008"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x3334"; - match "product" "0x1701"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x3340"; - match "product" "(0x011c|0x0326|0x0426|0x043a|0x051c|0x053a|0x071c|0x0b1c|0x0e3a|0x0f1c|0x0f3a|0x1326|0x191c|0x2326|0x3326)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x3708"; - match "product" "(0x20ce|0x21ce)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4113"; - match "product" "(0x0210|0x0211|0x0400|0x0410)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x413c"; - match "product" "(0x4001|0x4002|0x4003|0x4004|0x4005|0x4006|0x4007|0x4008|0x4009|0x8102|0x8104|0x8114|0x8115|0x8116|0x8117|0x8118|0x8128|0x8129|0x8133|0x8134|0x8135|0x8136|0x8137|0x8138|0x8180|0x8181|0x8182|0x9500)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4348"; - match "product" "0x5523"; - action "kldload uchcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4505"; - match "product" "0x0010"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4766"; - match "product" "0x0001"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5173"; - match "product" "0x1809"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5372"; - match "product" "0x2303"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5a57"; - match "product" "(0x0260|0x0280|0x0282|0x0283|0x0284|0x5257)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5e04"; - match "product" "0xce00"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x6189"; - match "product" "(0x182d|0x2068)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x6547"; - match "product" "0x0232"; - action "kldload uark"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x6891"; - match "product" "0xa727"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x7392"; - match "product" "(0x7318|0x7711|0x7717|0x7718)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x8516"; - match "product" "(0x2070|0x2770|0x2870|0x3070|0x3071|0x3072|0x3572)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9710"; - match "product" "(0x7703|0x7730|0x7820|0x7830|0x7840)"; - action "kldload umoscom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9e88"; - match "product" "0x9e8f"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0xdaae"; - match "product" "0xead6"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x02"; - match "intsubclass" "0x02"; - match "intprotocol" "0x01"; - action "kldload umodem"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x03"; - match "intsubclass" "0x01"; - match "intprotocol" "0x01"; - action "kldload ukbd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x03"; - match "intsubclass" "0x01"; - match "intprotocol" "0x02"; - action "kldload ums"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x07"; - match "intsubclass" "0x01"; - match "intprotocol" "0x01"; - action "kldload ulpt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x07"; - match "intsubclass" "0x01"; - match "intprotocol" "0x02"; - action "kldload ulpt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x07"; - match "intsubclass" "0x01"; - match "intprotocol" "0x03"; - action "kldload ulpt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0xe0"; - match "intsubclass" "0x01"; - match "intprotocol" "0x01"; - action "kldload ng_ubt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0xff"; - match "intsubclass" "0x5d"; - match "intprotocol" "0x01"; - action "kldload uhid"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x01"; - match "intsubclass" "0x01"; - action "kldload snd_uaudio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x01"; - match "intsubclass" "0x03"; - action "kldload snd_uaudio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x02"; - match "intsubclass" "0x88"; - action "kldload ufoma"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x03"; - action "kldload uhid"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x08"; - action "kldload umass"; -}; - -# 1631 usb_host entries processed - -- cgit v1.1 From dfc3b62a474375bbd3fdc0c0ccde2401ebf2b9f3 Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 25 Jun 2011 15:46:24 +0000 Subject: - Remove duplicate USB ID. MFC after: 3 days --- sys/dev/usb/wlan/if_zyd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index f8d905e..4221c34 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -229,7 +229,6 @@ static const STRUCT_USB_HOST_ID zyd_devs[] = { ZYD_ZD1211_DEV(ZYXEL, ZYAIRG220), ZYD_ZD1211_DEV(ZYXEL, G200V2), /* ZYD_ZD1211B */ - ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG_NF), ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG), ZYD_ZD1211B_DEV(ACCTON, ZD1211B), ZYD_ZD1211B_DEV(ASUS, A9T_WIFI), -- cgit v1.1 From 7bf33d894c26f24291366fab4fb5bdd5557ec031 Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 25 Jun 2011 15:51:44 +0000 Subject: - Export the USB device ID format to userspace tools. MFC after: 14 days --- sys/dev/usb/usb_lookup.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/usb/usbdi.h | 8 +++- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/sys/dev/usb/usb_lookup.c b/sys/dev/usb/usb_lookup.c index 3b2d16d..e03f9b6 100644 --- a/sys/dev/usb/usb_lookup.c +++ b/sys/dev/usb/usb_lookup.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include @@ -144,3 +146,108 @@ usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, } return (ENXIO); } + +/*------------------------------------------------------------------------* + * Export the USB device ID format we use to userspace tools. + *------------------------------------------------------------------------*/ +#if BYTE_ORDER == BIG_ENDIAN +#define U16_XOR "8" +#define U32_XOR "12" +#define U64_XOR "56" +#define U8_BITFIELD_XOR "7" +#define U16_BITFIELD_XOR "15" +#define U32_BITFIELD_XOR "31" +#define U64_BITFIELD_XOR "63" +#else +#define U16_XOR "0" +#define U32_XOR "0" +#define U64_XOR "0" +#define U8_BITFIELD_XOR "0" +#define U16_BITFIELD_XOR "0" +#define U32_BITFIELD_XOR "0" +#define U64_BITFIELD_XOR "0" +#endif + +#if USB_HAVE_COMPAT_LINUX +#define MFL_SIZE "1" +#else +#define MFL_SIZE "0" +#endif + +#ifdef KLD_MODULE +static const char __section("bus_autoconf_format") __used usb_id_format[] = { + + /* Declare that three different sections use the same format */ + + "usb_host_id{256,:}" + "usb_device_id{256,:}" + "usb_dual_id{256,:}" + + /* List size of fields in the usb_device_id structure */ + +#if ULONG_MAX >= 0xFFFFFFFFUL + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" +#if ULONG_MAX >= 0xFFFFFFFFFFFFFFFFULL + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" + "unused{0,8}" +#endif +#else +#error "Please update code." +#endif + + "idVendor[0]{" U16_XOR ",8}" + "idVendor[1]{" U16_XOR ",8}" + "idProduct[0]{" U16_XOR ",8}" + "idProduct[1]{" U16_XOR ",8}" + "bcdDevice_lo[0]{" U16_XOR ",8}" + "bcdDevice_lo[1]{" U16_XOR ",8}" + "bcdDevice_hi[0]{" U16_XOR ",8}" + "bcdDevice_hi[1]{" U16_XOR ",8}" + + "bDeviceClass{0,8}" + "bDeviceSubClass{0,8}" + "bDeviceProtocol{0,8}" + "bInterfaceClass{0,8}" + "bInterfaceSubClass{0,8}" + "bInterfaceProtocol{0,8}" + + "mf_vendor{" U8_BITFIELD_XOR ",1}" + "mf_product{" U8_BITFIELD_XOR ",1}" + "mf_dev_lo{" U8_BITFIELD_XOR ",1}" + "mf_dev_hi{" U8_BITFIELD_XOR ",1}" + + "mf_dev_class{" U8_BITFIELD_XOR ",1}" + "mf_dev_subclass{" U8_BITFIELD_XOR ",1}" + "mf_dev_protocol{" U8_BITFIELD_XOR ",1}" + "mf_int_class{" U8_BITFIELD_XOR ",1}" + + "mf_int_subclass{" U8_BITFIELD_XOR ",1}" + "mf_int_protocol{" U8_BITFIELD_XOR ",1}" + "unused{" U8_BITFIELD_XOR ",6}" + + "mfl_vendor{" U16_XOR "," MFL_SIZE "}" + "mfl_product{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_lo{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_hi{" U16_XOR "," MFL_SIZE "}" + + "mfl_dev_class{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_subclass{" U16_XOR "," MFL_SIZE "}" + "mfl_dev_protocol{" U16_XOR "," MFL_SIZE "}" + "mfl_int_class{" U16_XOR "," MFL_SIZE "}" + + "mfl_int_subclass{" U16_XOR "," MFL_SIZE "}" + "mfl_int_protocol{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" + "unused{" U16_XOR "," MFL_SIZE "}" +}; +#endif diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index a216879..d832c32 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -270,12 +270,15 @@ struct usb_device_id { uint8_t match_flag_product:1; uint8_t match_flag_dev_lo:1; uint8_t match_flag_dev_hi:1; + uint8_t match_flag_dev_class:1; uint8_t match_flag_dev_subclass:1; uint8_t match_flag_dev_protocol:1; uint8_t match_flag_int_class:1; + uint8_t match_flag_int_subclass:1; uint8_t match_flag_int_protocol:1; + uint8_t match_flag_unused:6; #if USB_HAVE_COMPAT_LINUX /* which fields to match against */ @@ -291,7 +294,10 @@ struct usb_device_id { #define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 #endif -}; +} __aligned(32); + +/* check that the size of the structure above is correct */ +extern char usb_device_id_assert[(sizeof(struct usb_device_id) == 32) ? 1 : -1]; #define USB_VENDOR(vend) \ .match_flag_vendor = 1, .idVendor = (vend) -- cgit v1.1 From 063a61ac2583c8d873a3df53ec1ebf20eba1a508 Mon Sep 17 00:00:00 2001 From: marius Date: Sat, 25 Jun 2011 16:01:45 +0000 Subject: As with EFI, OFW and U-Boot etc only compile FDT support on those architectures that actually use it. --- sys/boot/Makefile | 4 ---- sys/boot/Makefile.arm | 4 ++++ sys/boot/Makefile.powerpc | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/boot/Makefile b/sys/boot/Makefile index cfc82b9..06cffb1 100644 --- a/sys/boot/Makefile +++ b/sys/boot/Makefile @@ -8,10 +8,6 @@ SUBDIR+= ficl .endif -.if ${MK_FDT} != "no" -SUBDIR+= fdt -.endif - # Pick the machine-dependent subdir based on the target architecture. ADIR= ${MACHINE:S/amd64/i386/:S/powerpc64/powerpc/} .if exists(${.CURDIR}/${ADIR}/.) diff --git a/sys/boot/Makefile.arm b/sys/boot/Makefile.arm index f96104d..46fc574 100644 --- a/sys/boot/Makefile.arm +++ b/sys/boot/Makefile.arm @@ -1,3 +1,7 @@ # $FreeBSD$ +.if ${MK_FDT} != "no" +SUBDIR+= fdt +.endif + SUBDIR+= uboot diff --git a/sys/boot/Makefile.powerpc b/sys/boot/Makefile.powerpc index ca8c331..b7660f4 100644 --- a/sys/boot/Makefile.powerpc +++ b/sys/boot/Makefile.powerpc @@ -1,4 +1,8 @@ # $FreeBSD$ +.if ${MK_FDT} != "no" +SUBDIR+= fdt +.endif + SUBDIR+= ofw SUBDIR+= uboot -- cgit v1.1 From 1b609861c85e0538ad16d32d01c4bddc805df628 Mon Sep 17 00:00:00 2001 From: marius Date: Sat, 25 Jun 2011 16:13:56 +0000 Subject: The kerberos5 tools are only used as build tools but not otherwise and didn't get installed either. MFC after: 1 week --- kerberos5/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kerberos5/Makefile b/kerberos5/Makefile index 366540c..d87fa16 100644 --- a/kerberos5/Makefile +++ b/kerberos5/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -SUBDIR= doc tools lib libexec usr.bin usr.sbin +SUBDIR= doc lib libexec usr.bin usr.sbin # These are the programs which depend on Kerberos. KPROGS= lib/libpam \ -- cgit v1.1 From d717d950fa88ca5ea6d288d7a789bfd1b1709559 Mon Sep 17 00:00:00 2001 From: kientzle Date: Sat, 25 Jun 2011 16:27:49 +0000 Subject: If there is a read error reading Y/N confirmation from the keyboard, exit immediately with an error. If there is an error opening or reading a file to put into the archive, set the return value for a deferred error exit. PR: bin/154407 --- usr.bin/tar/util.c | 6 +++++- usr.bin/tar/write.c | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/usr.bin/tar/util.c b/usr.bin/tar/util.c index 858d472..4177e9c 100644 --- a/usr.bin/tar/util.c +++ b/usr.bin/tar/util.c @@ -226,7 +226,11 @@ yes(const char *fmt, ...) fflush(stderr); l = read(2, buff, sizeof(buff) - 1); - if (l <= 0) + if (l < 0) { + fprintf(stderr, "Keyboard read failed\n"); + exit(1); + } + if (l == 0) return (0); buff[l] = 0; diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c index e59f647..838dffb 100644 --- a/usr.bin/tar/write.c +++ b/usr.bin/tar/write.c @@ -919,6 +919,7 @@ write_entry_backend(struct bsdtar *bsdtar, struct archive *a, const char *pathname = archive_entry_sourcepath(entry); fd = open(pathname, O_RDONLY | O_BINARY); if (fd == -1) { + bsdtar->return_value = 1; if (!bsdtar->verbose) bsdtar_warnc(errno, "%s: could not open file", pathname); @@ -1020,6 +1021,12 @@ write_file_data(struct bsdtar *bsdtar, struct archive *a, progress += bytes_written; bytes_read = read(fd, bsdtar->buff, FILEDATABUFLEN); } + if (bytes_read < 0) { + bsdtar_warnc(errno, + "%s: Read error", + archive_entry_pathname(entry)); + bsdtar->return_value = 1; + } return 0; } -- cgit v1.1 From 628e425dc7e2da9ca525a72963f7603fc2358863 Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 25 Jun 2011 16:35:43 +0000 Subject: Define the minimum fractional period in terms of hz. We know hz is a magnitude smaller than itc_freq. A minimum period of 10*hz is sufficient precision. As a side-effect, the number of clocks per second, when the machine is idle, dropped by more than 50%. Be anal and define the maximum period to be at least 4G seconds. With a 64-bit counter and an ITC frequency that's expected to be always less than 4Ghz, it takes longer than that to wrap around. --- sys/ia64/ia64/clock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index 881c46f..74b2248 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -184,8 +184,8 @@ clock_configure(void *dummy) et->et_quality = 1000; et->et_frequency = itc_freq; et->et_min_period.sec = 0; - et->et_min_period.frac = ((1ul << 32) / itc_freq) << 32; - et->et_max_period.sec = 0xfffffff0 / itc_freq; + et->et_min_period.frac = (0x8000000000000000ul / (u_long)(10*hz)) << 1; + et->et_max_period.sec = ~0ul; /* XXX unless itc_freq >= (1<<32) */ et->et_max_period.frac = ((0xfffffffeul << 32) / itc_freq) << 32; et->et_start = ia64_clock_start; et->et_stop = ia64_clock_stop; -- cgit v1.1 From eec6fa48882cfb2fab4e8a04717d84d4727eb4ca Mon Sep 17 00:00:00 2001 From: hselasky Date: Sat, 25 Jun 2011 17:01:46 +0000 Subject: - Move bus_auto.conf back into /etc/devd/ - Rename bus_auto.conf into usb.conf Requested by: imp @ MFC after: 14 days --- etc/defaults/Makefile | 2 +- etc/defaults/devd.conf | 4275 ------------------------------------------------ etc/devd/Makefile | 2 +- etc/devd/usb.conf | 4275 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 4277 insertions(+), 4277 deletions(-) delete mode 100644 etc/defaults/devd.conf create mode 100644 etc/devd/usb.conf diff --git a/etc/defaults/Makefile b/etc/defaults/Makefile index 0d3a81a..c6555e6 100644 --- a/etc/defaults/Makefile +++ b/etc/defaults/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -FILES= bluetooth.device.conf devd.conf devfs.rules periodic.conf rc.conf +FILES= bluetooth.device.conf devfs.rules periodic.conf rc.conf NO_OBJ= FILESDIR= /etc/defaults diff --git a/etc/defaults/devd.conf b/etc/defaults/devd.conf deleted file mode 100644 index 5dbbd0a..0000000 --- a/etc/defaults/devd.conf +++ /dev/null @@ -1,4275 +0,0 @@ -# -# $FreeBSD$ -# -# This file was automatically generated by "tools/bus_autoconf.sh". -# Please do not edit! -# - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1290"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1292"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1294"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1297"; - match "intclass" "0xff"; - match "intsubclass" "0xfd"; - match "intprotocol" "0x01"; - action "kldload if_ipheth"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0104"; - match "product" "0x00be"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0123"; - match "product" "0x0001"; - action "kldload uep"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03e8"; - match "product" "0x0008"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03eb"; - match "product" "0x2109"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "0x0121"; - action "kldload ugensa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "(0x1016|0x1116|0x1216)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "(0x1b1d|0x1e1d)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "(0x2016|0x2116|0x2216|0x3016|0x3116|0x3216)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "0x3524"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "(0x4016|0x4116|0x4216|0x5016|0x5116|0x5216)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "0x811c"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x03f0"; - match "product" "0xca02"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0402"; - match "product" "0x5632"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0403"; - match "product" "(0x6001|0x6004|0x6010|0x6011|0x8372|0x9e90|0xcc48|0xcc49|0xcc4a|0xd678|0xe6c8|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xee18|0xf608|0xf60b|0xf850|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfc08|0xfc09|0xfc0b|0xfc0c|0xfc0d|0xfc82)"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0408"; - match "product" "0x0304"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0408"; - match "product" "(0x1000|0xea02|0xea03|0xea04|0xea05|0xea06)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0409"; - match "product" "(0x00d5|0x00d6|0x00d7|0x8024|0x8025)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "(0x0001|0x0005|0x0009)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x0012"; - action "kldload if_rue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x003d"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "(0x005e|0x0066|0x0067)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x006e"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x008b"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x00b3"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "(0x00d8|0x00d9)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x00da"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x00e8"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "(0x0116|0x0119)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x012e"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "0x0137"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0411"; - match "product" "(0x0148|0x0150|0x015d|0x016f)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0413"; - match "product" "0x2101"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0423"; - match "product" "(0x000a|0x000c)"; - action "kldload if_cue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x043e"; - match "product" "0x9c01"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045a"; - match "product" "(0x5001|0x5002)"; - action "kldload urio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045b"; - match "product" "0x0053"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045e"; - match "product" "0x0079"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045e"; - match "product" "0x007a"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x045e"; - match "product" "(0x00ce|0x0400|0x0401|0x0402|0x0403|0x0404|0x0405|0x0406|0x0407|0x0408|0x0409|0x040a|0x040b|0x040c|0x040d|0x040e|0x040f|0x0410|0x0411|0x0412|0x0413|0x0414|0x0415|0x0416|0x0417|0x0432|0x0433|0x0434|0x0435|0x0436|0x0437|0x0438|0x0439|0x043a|0x043b|0x043c|0x043d|0x043e|0x043f|0x0440|0x0441|0x0442|0x0443|0x0444|0x0445|0x0446|0x0447|0x0448|0x0449|0x044a|0x044b|0x044c|0x044d|0x044e|0x044f|0x0450|0x0451|0x0452|0x0453|0x0454|0x0455|0x0456|0x0457|0x0458|0x0459|0x045a|0x045b|0x045c|0x045d|0x045e|0x045f|0x0460|0x0461|0x0462|0x0463|0x0464|0x0465|0x0466|0x0467|0x0468|0x0469|0x046a|0x046b|0x046c|0x046d|0x046e|0x046f|0x0470|0x0471|0x0472|0x0473|0x0474|0x0475|0x0476|0x0477|0x0478|0x0479|0x047a|0x047b|0x04c8|0x04c9|0x04ca|0x04cb|0x04cc|0x04cd|0x04ce|0x04d7|0x04d8|0x04d9|0x04da|0x04db|0x04dc|0x04dd|0x04de|0x04df|0x04e0|0x04e1|0x04e2|0x04e3|0x04e4|0x04e5|0x04e6|0x04e7|0x04e8|0x04e9|0x04ea)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0471"; - match "product" "0x066a"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0471"; - match "product" "0x1236"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0471"; - match "product" "0x200f"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0482"; - match "product" "0x0203"; - action "kldload umodem"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0489"; - match "product" "(0xe000|0xe003)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x049f"; - match "product" "(0x0003|0x0032)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x049f"; - match "product" "0x505a"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04a4"; - match "product" "0x0014"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04a5"; - match "product" "0x4027"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04a5"; - match "product" "0x4068"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04ad"; - match "product" "(0x0301|0x0302|0x0303|0x0306)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04b4"; - match "product" "0x1002"; - action "kldload ufm"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04b7"; - match "product" "0x0531"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04b8"; - match "product" "(0x0521|0x0522)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bb"; - match "product" "0x0901"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bb"; - match "product" "(0x0904|0x0913)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bb"; - match "product" "0x0930"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bb"; - match "product" "(0x0944|0x0945|0x0947|0x0948)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bb"; - match "product" "(0x0a03|0x0a0e)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04bf"; - match "product" "(0x0115|0x0117)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04c5"; - match "product" "(0x1058|0x1079)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04da"; - match "product" "0x2500"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04da"; - match "product" "0x3900"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04dd"; - match "product" "(0x8004|0x8005|0x8006|0x8007|0x9031)"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04dd"; - match "product" "(0x9102|0x9121|0x9123|0x9151|0x91ac|0x9242)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04e8"; - match "product" "(0x5f00|0x5f01|0x5f02|0x5f03|0x5f04)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04e8"; - match "product" "0x6601"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04e8"; - match "product" "(0x6611|0x6613|0x6615|0x6617|0x6619|0x661b|0x662e|0x6630|0x6632)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04e8"; - match "product" "0x8001"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04f1"; - match "product" "0x3008"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x04f1"; - match "product" "(0x3011|0x3012)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0502"; - match "product" "(0x1631|0x1632|0x16e1|0x16e2|0x16e3)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0506"; - match "product" "(0x03e8|0x11f8)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0506"; - match "product" "0x4601"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x0103"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x0109"; - action "kldload umct"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x0121"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x0257"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x0409"; - action "kldload umct"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x1203"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x4050"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x5055"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x7050"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "(0x7050|0x7051)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x705a"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x705c"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x705e"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "(0x8053|0x805c|0x815c|0x825a)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x905b"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x050d"; - match "product" "0x935a"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0525"; - match "product" "0x1080"; - action "kldload udbp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0525"; - match "product" "0xa4a2"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0536"; - match "product" "0x01a0"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0543"; - match "product" "(0x0ed9|0x1527|0x1529|0x152b|0x152e|0x1921|0x1922|0x1923)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0547"; - match "product" "0x2008"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0547"; - match "product" "0x2720"; - action "kldload udbp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x054c"; - match "product" "(0x0038|0x0066|0x0095|0x009a|0x00da|0x0169)"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x054c"; - match "product" "0x0437"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0557"; - match "product" "0x2002"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0557"; - match "product" "0x2007"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0557"; - match "product" "0x2008"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0557"; - match "product" "0x2009"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0557"; - match "product" "0x4000"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x055d"; - match "product" "0x2018"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0565"; - match "product" "0x0001"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0565"; - match "product" "(0x0002|0x0003|0x0005)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0567"; - match "product" "(0x2000|0x2002)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x056c"; - match "product" "0x8007"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x056e"; - match "product" "(0x200c|0x4002|0x4005|0x400b|0x4010)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x056e"; - match "product" "(0x5003|0x5004)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x056e"; - match "product" "0xabc1"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x057c"; - match "product" "(0x2200|0x3800)"; - action "kldload ng_ubt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0584"; - match "product" "0xb000"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0584"; - match "product" "0xb020"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0586"; - match "product" "(0x3401|0x3407|0x3409|0x340a|0x340f|0x3410)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0586"; - match "product" "(0x3416|0x341a)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x058f"; - match "product" "0x9720"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05a6"; - match "product" "0x0101"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "(0x020d|0x020e|0x020f|0x0215|0x0217|0x0218|0x0219|0x021a|0x021b|0x021c|0x0229|0x022a|0x022b|0x030a|0x030b)"; - action "kldload atp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ac"; - match "product" "0x1402"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05ad"; - match "product" "0x0fba"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05c6"; - match "product" "(0x6000|0x6613)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05cc"; - match "product" "0x3000"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05db"; - match "product" "(0x0003|0x0005|0x0009|0x000a|0x0011)"; - action "kldload uvscom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05e0"; - match "product" "(0x2000|0x2001|0x2002|0x2003|0x2004|0x2005|0x2006|0x2007|0x2008|0x2009|0x200a)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05e3"; - match "product" "0x0501"; - action "kldload udbp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x05e9"; - match "product" "(0x0008|0x0009)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x066b"; - match "product" "(0x200c|0x2202)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x066b"; - match "product" "0x2202"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x066b"; - match "product" "(0x2203|0x2204|0x2206|0x400b)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0675"; - match "product" "0x0550"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067b"; - match "product" "(0x0000|0x0001)"; - action "kldload udbp"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067b"; - match "product" "(0x04bb|0x0609|0x0611|0x0612|0x1234|0x206a|0x2303)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067b"; - match "product" "0x2501"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067b"; - match "product" "(0x331a|0xaaa0|0xaaa2)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067c"; - match "product" "0x1001"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x067e"; - match "product" "0x1001"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0681"; - match "product" "0x3c06"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x06e1"; - match "product" "(0x0008|0x0009)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x06f8"; - match "product" "0xe000"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x06f8"; - match "product" "(0xe010|0xe020)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x06f8"; - match "product" "0xe030"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0707"; - match "product" "0x0100"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0707"; - match "product" "(0x0200|0x0201)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0707"; - match "product" "0xee13"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0707"; - match "product" "0xee13"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0711"; - match "product" "(0x0200|0x0210|0x0230)"; - action "kldload umct"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0731"; - match "product" "(0x0528|0x2003)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0745"; - match "product" "0x0001"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0745"; - match "product" "0x1000"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0769"; - match "product" "0x11f2"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0769"; - match "product" "0x11f3"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0769"; - match "product" "0x31f3"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x077b"; - match "product" "0x2226"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0789"; - match "product" "0x010c"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0789"; - match "product" "0x0160"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0789"; - match "product" "(0x0162|0x0163|0x0164)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x078b"; - match "product" "0x1234"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x079b"; - match "product" "0x0027"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x079b"; - match "product" "(0x004a|0x0062)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07a6"; - match "product" "(0x07c2|0x0986|0x8511|0x8513|0x8515)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "0x0001"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "(0x0004|0x000d)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "0x0017"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "0x002a"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "(0x002d|0x002e)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "(0x002f|0x003c|0x003f|0x0041|0x0042)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07aa"; - match "product" "0x9601"; - action "kldload if_udav"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "(0x110c|0x200c)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "(0x2770|0x2870|0x3070|0x3071|0x3072)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "0x4000"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "(0x4002|0x4003|0x4004|0x4007|0x400b|0x400c|0x4102|0x4104)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "0x420a"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "0x6001"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "0xabc1"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07b8"; - match "product" "(0xb21b|0xb21c|0xb21d|0xb21e|0xb21f)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07c9"; - match "product" "0xb100"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07cf"; - match "product" "(0x2001|0x2002|0x2003)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07d1"; - match "product" "0x3a0c"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07d1"; - match "product" "(0x3c03|0x3c04|0x3c06|0x3c07)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x07d1"; - match "product" "(0x3c09|0x3c0a|0x3c0b|0x3c0d|0x3c0e|0x3c0f|0x3c11|0x3c13|0x3c15|0x3c16)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x081e"; - match "product" "0xdf00"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x082d"; - match "product" "(0x0100|0x0200|0x0300)"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0830"; - match "product" "(0x0001|0x0002|0x0003|0x0020|0x0031|0x0040|0x0050|0x0060|0x0061|0x0070)"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0833"; - match "product" "(0x012e|0x039f)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0x1046"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0x4506"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0x4506"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0x4508"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0x4521"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0x5046"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "(0x6618|0x7511|0x7512|0x7522|0x8522|0xa512|0xa618|0xa701|0xa702|0xb522|0xc522|0xd522)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0xe501"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0841"; - match "product" "0x0001"; - action "kldload urio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "(0x1001|0x1002)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "0x1020"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "0x1040"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "0x4240"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "0x4260"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "0x4300"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0846"; - match "product" "(0x6100|0x6a00)"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0856"; - match "product" "0xac01"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x085a"; - match "product" "(0x0008|0x0009)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x086e"; - match "product" "0x1920"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x087d"; - match "product" "0x5704"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08d1"; - match "product" "0x0001"; - action "kldload if_cue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08d1"; - match "product" "0x0003"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08dd"; - match "product" "(0x0986|0x0987|0x0988|0x8511)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08dd"; - match "product" "0x90ff"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08e6"; - match "product" "0x5501"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x08fd"; - match "product" "0x000a"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0915"; - match "product" "(0x2000|0x2002)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x091e"; - match "product" "0x0004"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0921"; - match "product" "0x1001"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0930"; - match "product" "(0x0700|0x0705|0x0706|0x0707|0x0708|0x0709|0x070a|0x070b)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0930"; - match "product" "0x0a07"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0930"; - match "product" "(0x0d45|0x1302)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x093c"; - match "product" "(0x0601|0x0701)"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x094b"; - match "product" "0x0001"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0951"; - match "product" "0x0008"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0951"; - match "product" "0x000a"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x095a"; - match "product" "0x3003"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0960"; - match "product" "(0x0065|0x0066|0x0067)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0961"; - match "product" "0x0010"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x099e"; - match "product" "(0x0052|0x4000)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x09aa"; - match "product" "0x1000"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x09d7"; - match "product" "0x0100"; - action "kldload ugensa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0a46"; - match "product" "(0x0268|0x8515|0x9601)"; - action "kldload if_udav"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0a5c"; - match "product" "0x2033"; - action "kldload ubtbcmfw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0ace"; - match "product" "(0x1211|0x1215)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "(0x5000|0x6000|0x6050|0x6100|0x6150|0x6200|0x6250|0x6300|0x6350|0x6500|0x6501|0x6600|0x6601|0x6701|0x6721|0x6741|0x6761|0x6800|0x6901)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "0x6911"; - action "kldload uhso"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "0x6971"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "0x6971"; - action "kldload uhso"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "0x7001"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "0x7011"; - action "kldload uhso"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "(0x7021|0x7041|0x7061|0x7100|0x7201|0x7211)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "(0x7251|0x7301|0x7361|0x7381|0x7401|0x7501)"; - action "kldload uhso"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "0x7601"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "(0x7601|0xc031|0xd013|0xd031)"; - action "kldload uhso"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "0xd033"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0af0"; - match "product" "(0xd033|0xd055|0xd055)"; - action "kldload uhso"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b05"; - match "product" "(0x1706|0x1707)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b05"; - match "product" "(0x170c|0x171b)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b05"; - match "product" "0x171d"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b05"; - match "product" "(0x1723|0x1724)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b05"; - match "product" "(0x1731|0x1732|0x1742|0x1760|0x1761|0x1784|0x1790)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b05"; - match "product" "(0x4200|0x4201|0x4202|0x420f|0x9200|0x9202)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b39"; - match "product" "0x0109"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b39"; - match "product" "0x0421"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b3b"; - match "product" "(0x1630|0x5630|0x6630)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b41"; - match "product" "0x0011"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b63"; - match "product" "0x6530"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b8c"; - match "product" "0x2303"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0b95"; - match "product" "(0x1720|0x1780|0x7720|0x772a)"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0baf"; - match "product" "0x0118"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0baf"; - match "product" "0x0121"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bb2"; - match "product" "0x6098"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bb4"; - match "product" "(0x00ce|0x00cf|0x00cf|0x0a01|0x0a02|0x0a03|0x0a04|0x0a05|0x0a06|0x0a07|0x0a08|0x0a09|0x0a0a|0x0a0b|0x0a0c|0x0a0d|0x0a0e|0x0a0f|0x0a10|0x0a11|0x0a12|0x0a13|0x0a14|0x0a15|0x0a16|0x0a17|0x0a18|0x0a19|0x0a1a|0x0a1b|0x0a1c|0x0a1d|0x0a1e|0x0a1f|0x0a20|0x0a21|0x0a22|0x0a23|0x0a24|0x0a25|0x0a26|0x0a27|0x0a28|0x0a29|0x0a2a|0x0a2b|0x0a2c|0x0a2d|0x0a2e|0x0a2f|0x0a30|0x0a31|0x0a32|0x0a33|0x0a34|0x0a35|0x0a36|0x0a37|0x0a38|0x0a39|0x0a3a|0x0a3b|0x0a3c|0x0a3d|0x0a3e|0x0a3f|0x0a40|0x0a41|0x0a42|0x0a43|0x0a44|0x0a45|0x0a46|0x0a47|0x0a48|0x0a49|0x0a4a|0x0a4b|0x0a4c|0x0a4d|0x0a4e|0x0a4f|0x0a50|0x0a51|0x0a52|0x0a53|0x0a54|0x0a55|0x0a56|0x0a57|0x0a58|0x0a59|0x0a5a|0x0a5b|0x0a5c|0x0a5d|0x0a5e|0x0a5f|0x0a60|0x0a61|0x0a62|0x0a63|0x0a64|0x0a65|0x0a66|0x0a67|0x0a68|0x0a69|0x0a6a|0x0a6b|0x0a6c|0x0a6d|0x0a6e|0x0a6f|0x0a70|0x0a71|0x0a72|0x0a73|0x0a74|0x0a75|0x0a76|0x0a77|0x0a78|0x0a79|0x0a7a|0x0a7b|0x0a7c|0x0a7d|0x0a7e|0x0a7f|0x0a80|0x0a81|0x0a82|0x0a83|0x0a84|0x0a85|0x0a86|0x0a87|0x0a88|0x0a89|0x0a8a|0x0a8b|0x0a8c|0x0a8d|0x0a8e|0x0a8f|0x0a90|0x0a91|0x0a92|0x0a93|0x0a94|0x0a95|0x0a96|0x0a97|0x0a98|0x0a99|0x0a9a|0x0a9b|0x0a9c|0x0a9d|0x0a9e|0x0a9f|0x0bce)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bda"; - match "product" "0x8150"; - action "kldload if_rue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bda"; - match "product" "(0x8187|0x8189|0x8197|0x8198)"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bed"; - match "product" "(0x1100|0x1101)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bf8"; - match "product" "0x1001"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0bf8"; - match "product" "0x1009"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c44"; - match "product" "0x03a2"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c88"; - match "product" "0x17da"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c88"; - match "product" "0x17da"; - action "kldload ugensa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c88"; - match "product" "0x180a"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0c8e"; - match "product" "0x6000"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cad"; - match "product" "0x9001"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cde"; - match "product" "0x0008"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cde"; - match "product" "0x0011"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cde"; - match "product" "0x0012"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cde"; - match "product" "0x0015"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cde"; - match "product" "0x001a"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cde"; - match "product" "(0x0022|0x0025)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0cf3"; - match "product" "(0x0001|0x0003|0x0005)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0d8e"; - match "product" "0x3762"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0d8e"; - match "product" "(0x7801|0x7811)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db0"; - match "product" "(0x3820|0x3821|0x3822|0x3870|0x3871)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db0"; - match "product" "(0x6861|0x6865|0x6869)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db0"; - match "product" "(0x6874|0x6877)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db0"; - match "product" "(0x6899|0x821a|0x822a|0x870a|0x871a|0x899a)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db0"; - match "product" "(0xa861|0xa874)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0db7"; - match "product" "0x0002"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "0x000d"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "0x0017"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "0x0021"; - action "kldload if_mos"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "0x0028"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "(0x002b|0x002c|0x002d|0x0039|0x003b|0x003c|0x003d|0x003e|0x003f|0x0040|0x0041|0x0042|0x0047|0x0048|0x004a|0x004d)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "0x061c"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "(0x9071|0x9075)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df6"; - match "product" "(0x90ac|0x9712)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0df7"; - match "product" "0x0620"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e0b"; - match "product" "(0x9031|0x9041)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e55"; - match "product" "0x110b"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e66"; - match "product" "(0x0001|0x0003|0x0009|0x000b)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e66"; - match "product" "0x400c"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e67"; - match "product" "0x0002"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0e7e"; - match "product" "0x1001"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0ea0"; - match "product" "0x6858"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eab"; - match "product" "0xc893"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eb0"; - match "product" "0x9020"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eb0"; - match "product" "0x9021"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eba"; - match "product" "(0x1080|0x2080)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0eef"; - match "product" "(0x0001|0x0002)"; - action "kldload uep"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f3d"; - match "product" "0x0112"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f3d"; - match "product" "0x0112"; - action "kldload ugensa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f4e"; - match "product" "0x0200"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f88"; - match "product" "0x3012"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f88"; - match "product" "0x3014"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f94"; - match "product" "0x0001"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0f98"; - match "product" "0x0201"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0fb8"; - match "product" "(0x3001|0x3002|0x3003|0x4001)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0fcf"; - match "product" "(0x1003|0x1004|0x1006)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x0fe6"; - match "product" "(0x8101|0x9700)"; - action "kldload if_udav"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x100d"; - match "product" "(0x9031|0x9032)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1011"; - match "product" "0x3198"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1044"; - match "product" "0x8001"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1044"; - match "product" "0x8002"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1044"; - match "product" "0x8007"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1044"; - match "product" "(0x8008|0x800a)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1044"; - match "product" "(0x800b|0x800c|0x800d)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1066"; - match "product" "(0x00ce|0x0300|0x0500|0x0600|0x0700)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x106c"; - match "product" "0x3701"; - action "kldload umodem"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10a6"; - match "product" "0xaa26"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10ab"; - match "product" "0x10c5"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10b5"; - match "product" "0xac70"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10b5"; - match "product" "0xac70"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10bd"; - match "product" "0x1427"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10c4"; - match "product" "(0x0f91|0x1101|0x1601|0x800a|0x803b|0x8043|0x8044)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10c4"; - match "product" "0x8053"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10c4"; - match "product" "(0x8066|0x806f|0x807a|0x80ca|0x80dd|0x80ed|0x80f6|0x8115|0x813d|0x813f|0x814a|0x814a|0x814b|0x8156|0x815e|0x818b|0x819f|0x81a6|0x81ac|0x81ad|0x81c8|0x81e2|0x81e7|0x81e8|0x81f2|0x8218|0x822b|0x826b|0x8293|0x82f9|0x8341|0x8382|0x83a8|0x8411|0x846e|0x8477|0xea60|0xea61|0xea71|0xf001|0xf002|0xf003|0xf004)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10c5"; - match "product" "0xea61"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x10ce"; - match "product" "0xea61"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1114"; - match "product" "(0x0001|0x0004|0x0006)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x114b"; - match "product" "0x0110"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x114b"; - match "product" "0x0150"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1163"; - match "product" "0x0100"; - action "kldload ucycom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1182"; - match "product" "0x1388"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1186"; - match "product" "0x3e04"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1189"; - match "product" "0x0893"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1199"; - match "product" "(0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0112|0x0120|0x0218)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1199"; - match "product" "0x0218"; - action "kldload umodem"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1199"; - match "product" "(0x0220|0x0224|0x0fff|0x6802|0x6803|0x6804|0x6805|0x6808|0x6809|0x6812|0x6813|0x6815|0x6816|0x6820|0x6821|0x6822|0x6832|0x6833|0x6834|0x6835|0x6838|0x6839|0x683a|0x683b|0x683c|0x683d|0x683e|0x6850|0x6851|0x6852|0x6853|0x6855|0x6856|0x6859|0x685a|0x6880|0x6890|0x6891|0x6892|0x6893|0x68a3)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11ad"; - match "product" "0x0701"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11d9"; - match "product" "(0x1002|0x1003)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11f5"; - match "product" "(0x0001|0x0003|0x0004|0x0005)"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11f6"; - match "product" "0x2001"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x11f7"; - match "product" "0x02df"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1231"; - match "product" "(0xce01|0xce02)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x126f"; - match "product" "0xa006"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x129b"; - match "product" "0x1666"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x129b"; - match "product" "0x1828"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x12d1"; - match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1465|0x14ac|0x1520)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x12ef"; - match "product" "0x0100"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1342"; - match "product" "0x0204"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1371"; - match "product" "(0x9022|0x9032)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1371"; - match "product" "0x9401"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1385"; - match "product" "(0x4250|0x5f00|0x5f02)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13ad"; - match "product" "0x9999"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13b1"; - match "product" "0x000c"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13b1"; - match "product" "(0x000d|0x0011)"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13b1"; - match "product" "0x0018"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13b1"; - match "product" "0x001a"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13b1"; - match "product" "(0x0020|0x0023)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13b1"; - match "product" "0x0024"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13d2"; - match "product" "0x0400"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x13d3"; - match "product" "(0x3247|0x3262|0x3273|0x3284|0x3305)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1410"; - match "product" "(0x1100|0x1110|0x1120|0x1130|0x1400|0x1410|0x1420|0x1430|0x1450|0x2100|0x2110|0x2120|0x2130|0x2400|0x2410|0x2420|0x4100|0x4400|0x5010|0x5100|0x6000|0x6002|0x7042)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1416"; - match "product" "0x1110"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1435"; - match "product" "0x0427"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1435"; - match "product" "0x0711"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1435"; - match "product" "(0x0826|0x082a)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1453"; - match "product" "0x4026"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1472"; - match "product" "0x0009"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1482"; - match "product" "0x3c09"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1485"; - match "product" "(0x0001|0x0002)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "0x1706"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "0x2070"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "0x2570"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "(0x2573|0x2671)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "(0x2770|0x2870|0x3070|0x3071|0x3072|0x3370|0x3572|0x8070)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "0x9020"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x148f"; - match "product" "0x9021"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14b2"; - match "product" "0x3c02"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14b2"; - match "product" "(0x3c06|0x3c07|0x3c08|0x3c09|0x3c11|0x3c12)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14b2"; - match "product" "0x3c22"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14b2"; - match "product" "(0x3c23|0x3c25|0x3c25|0x3c27|0x3c28)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14ea"; - match "product" "0xab10"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14ea"; - match "product" "0xab11"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x14ea"; - match "product" "0xab13"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1555"; - match "product" "0x0004"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1557"; - match "product" "0x7720"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1557"; - match "product" "0x8150"; - action "kldload if_rue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x157e"; - match "product" "0x3006"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x157e"; - match "product" "(0x300a|0x300b|0x300d)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x157e"; - match "product" "0x300e"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x157e"; - match "product" "0x3204"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x157e"; - match "product" "0x3205"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1582"; - match "product" "0x6003"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x15a9"; - match "product" "0x0004"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x15a9"; - match "product" "(0x0006|0x0010)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x15c5"; - match "product" "0x0008"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x15e8"; - match "product" "(0x9100|0x9110)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1614"; - match "product" "(0x0800|0x0802|0x7002)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1631"; - match "product" "0x6200"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1631"; - match "product" "0xc019"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1645"; - match "product" "(0x0005|0x0008|0x8005)"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x166a"; - match "product" "0x0303"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x167b"; - match "product" "0x4001"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x168c"; - match "product" "0x0001"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1690"; - match "product" "0x0601"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1690"; - match "product" "(0x0710|0x0712)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1690"; - match "product" "0x0722"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1690"; - match "product" "(0x0740|0x0744)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16ab"; - match "product" "(0x7801|0x7811)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d5"; - match "product" "(0x6202|0x6501)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d5"; - match "product" "0x6501"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d5"; - match "product" "0x6502"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d5"; - match "product" "0x6502"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d6"; - match "product" "(0x0001|0x0001)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d8"; - match "product" "(0x6006|0x6280)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16d8"; - match "product" "0x6280"; - action "kldload ugensa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x16dc"; - match "product" "(0x0010|0x0011|0x0012|0x0015)"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1726"; - match "product" "0x1000"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1726"; - match "product" "0x1000"; - action "kldload ubsa"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1737"; - match "product" "0x0039"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1737"; - match "product" "(0x0070|0x0071)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1737"; - match "product" "0x0073"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1737"; - match "product" "(0x0077|0x0078|0x0079)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1740"; - match "product" "(0x0605|0x0615)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1740"; - match "product" "0x2000"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1740"; - match "product" "(0x9701|0x9702|0x9703|0x9705|0x9706|0x9707|0x9708|0x9709|0x9801)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1761"; - match "product" "0x0b05"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x177f"; - match "product" "(0x0153|0x0302|0x0313)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x17f4"; - match "product" "0xaaaa"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1843"; - match "product" "0x0200"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18c5"; - match "product" "0x0002"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18c5"; - match "product" "(0x0008|0x0012)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18e8"; - match "product" "(0x6196|0x6229)"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18e8"; - match "product" "0x6232"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18e8"; - match "product" "0x6238"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18e8"; - match "product" "0x6259"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x18ef"; - match "product" "0xe00f"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x19d2"; - match "product" "(0x0001|0x0002|0x0003|0x0004|0x0005|0x0006|0x0007|0x0008|0x0009|0x000a|0x000b|0x000c|0x000d|0x000e|0x000f|0x0010|0x0011|0x0012|0x0013|0x0014|0x0015|0x0016|0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0030|0x0031|0x0032|0x0033|0x0037|0x0039|0x0042|0x0043|0x0048|0x0049|0x0051|0x0052|0x0053|0x0054|0x0055|0x0057|0x0058|0x0059|0x0060|0x0061|0x0062|0x0063|0x0064|0x0066|0x0069|0x0070|0x0073|0x0076|0x0078|0x0082|0x0086|0x0117|0x2000|0x2002|0x2003|0xfff1|0xfff5|0xfffe)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1a86"; - match "product" "0x7523"; - action "kldload uchcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1a8d"; - match "product" "(0x1002|0x1003|0x1004|0x1005|0x1006|0x1007|0x1008|0x1009|0x100a|0x100b|0x100c|0x100d|0x100e|0x100f|0x1010|0x1011|0x1012)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1b3d"; - match "product" "0x0153"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1b75"; - match "product" "0x3072"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1b75"; - match "product" "0x8187"; - action "kldload if_urtw"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1bbb"; - match "product" "(0x0000|0xf000)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1bc7"; - match "product" "(0x1003|0x1004)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1be3"; - match "product" "0x07a6"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1c9e"; - match "product" "(0x6061|0x9603|0xf000)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1cf1"; - match "product" "(0x0001|0x0004)"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1d09"; - match "product" "0x4000"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1d4d"; - match "product" "(0x0002|0x000c|0x000e|0x0010)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1da5"; - match "product" "(0x4512|0x4515|0x4519|0x4523)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1e0e"; - match "product" "(0x9000|0x9200|0xce16)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x1eda"; - match "product" "0x2310"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "0x1a00"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "0x200c"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "(0x3a00|0x3a02|0x3a04)"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "0x3c00"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "0x3c05"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "(0x3c09|0x3c0a)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "0x4000"; - action "kldload if_kue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2001"; - match "product" "(0x4001|0x4002|0x4003|0x400b|0x4102|0xabc1)"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "0x5303"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "0xab01"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "(0xab24|0xab25)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "0xab50"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "(0xc007|0xed01)"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "0xed02"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2019"; - match "product" "(0xed06|0xed14)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x203d"; - match "product" "(0x1480|0x14a1|0x14a9)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x20b8"; - match "product" "0x8888"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x20b9"; - match "product" "0x1682"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x22b8"; - match "product" "(0x4204|0x4214|0x4224|0x4234|0x4244)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x22b8"; - match "product" "(0x600c|0x6027)"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x2478"; - match "product" "0x2008"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x3334"; - match "product" "0x1701"; - action "kldload if_aue"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x3340"; - match "product" "(0x011c|0x0326|0x0426|0x043a|0x051c|0x053a|0x071c|0x0b1c|0x0e3a|0x0f1c|0x0f3a|0x1326|0x191c|0x2326|0x3326)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x3708"; - match "product" "(0x20ce|0x21ce)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4113"; - match "product" "(0x0210|0x0211|0x0400|0x0410)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x413c"; - match "product" "(0x4001|0x4002|0x4003|0x4004|0x4005|0x4006|0x4007|0x4008|0x4009)"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x413c"; - match "product" "(0x8102|0x8104)"; - action "kldload if_upgt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x413c"; - match "product" "(0x8114|0x8115|0x8116|0x8117|0x8118|0x8128|0x8129|0x8133|0x8134|0x8135|0x8136|0x8137|0x8138|0x8180|0x8181|0x8182)"; - action "kldload u3g"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x413c"; - match "product" "0x9500"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4348"; - match "product" "0x5523"; - action "kldload uchcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4505"; - match "product" "0x0010"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x4766"; - match "product" "0x0001"; - action "kldload uvisor"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5173"; - match "product" "0x1809"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5372"; - match "product" "0x2303"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5a57"; - match "product" "0x0260"; - action "kldload if_ural"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5a57"; - match "product" "(0x0280|0x0282|0x0283|0x0284|0x5257)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x5e04"; - match "product" "0xce00"; - action "kldload uipaq"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x6189"; - match "product" "0x182d"; - action "kldload if_axe"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x6189"; - match "product" "0x2068"; - action "kldload uplcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x6547"; - match "product" "0x0232"; - action "kldload uark"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x6891"; - match "product" "0xa727"; - action "kldload if_zyd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x7392"; - match "product" "0x7318"; - action "kldload if_rum"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x7392"; - match "product" "(0x7711|0x7717|0x7718)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x8516"; - match "product" "(0x2070|0x2770|0x2870|0x3070|0x3071|0x3072|0x3572)"; - action "kldload if_run"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9710"; - match "product" "0x7703"; - action "kldload umoscom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9710"; - match "product" "0x7730"; - action "kldload if_mos"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9710"; - match "product" "0x7820"; - action "kldload umcs"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9710"; - match "product" "0x7830"; - action "kldload if_mos"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9710"; - match "product" "0x7840"; - action "kldload umcs"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x9e88"; - match "product" "0x9e8f"; - action "kldload uftdi"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0xdaae"; - match "product" "0xead6"; - action "kldload uslcom"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x02"; - match "intsubclass" "0x02"; - match "intprotocol" "0x01"; - action "kldload umodem"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x03"; - match "intsubclass" "0x01"; - match "intprotocol" "0x01"; - action "kldload ukbd"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x03"; - match "intsubclass" "0x01"; - match "intprotocol" "0x02"; - action "kldload ums"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x07"; - match "intsubclass" "0x01"; - match "intprotocol" "0x01"; - action "kldload ulpt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x07"; - match "intsubclass" "0x01"; - match "intprotocol" "0x02"; - action "kldload ulpt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x07"; - match "intsubclass" "0x01"; - match "intprotocol" "0x03"; - action "kldload ulpt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0xe0"; - match "intsubclass" "0x01"; - match "intprotocol" "0x01"; - action "kldload ng_ubt"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0xff"; - match "intsubclass" "0x5d"; - match "intprotocol" "0x01"; - action "kldload uhid"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x01"; - match "intsubclass" "0x01"; - action "kldload snd_uaudio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x01"; - match "intsubclass" "0x03"; - action "kldload snd_uaudio"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "(host|device)"; - match "intclass" "0x02"; - match "intsubclass" "0x06"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "(host|device)"; - match "intclass" "0x02"; - match "intsubclass" "0x0a"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "(host|device)"; - match "intclass" "0x02"; - match "intsubclass" "0x0d"; - action "kldload if_cdce"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x02"; - match "intsubclass" "0x88"; - action "kldload ufoma"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x03"; - action "kldload uhid"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "intclass" "0x08"; - action "kldload umass"; -}; - -# 1634 USB entries processed - diff --git a/etc/devd/Makefile b/etc/devd/Makefile index ad434f2..8d7246a 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -FILES= asus.conf uath.conf +FILES= asus.conf uath.conf usb.conf NO_OBJ= FILESDIR= /etc/devd diff --git a/etc/devd/usb.conf b/etc/devd/usb.conf new file mode 100644 index 0000000..5dbbd0a --- /dev/null +++ b/etc/devd/usb.conf @@ -0,0 +1,4275 @@ +# +# $FreeBSD$ +# +# This file was automatically generated by "tools/bus_autoconf.sh". +# Please do not edit! +# + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1290"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1292"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1294"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1297"; + match "intclass" "0xff"; + match "intsubclass" "0xfd"; + match "intprotocol" "0x01"; + action "kldload if_ipheth"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0104"; + match "product" "0x00be"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0123"; + match "product" "0x0001"; + action "kldload uep"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03e8"; + match "product" "0x0008"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03eb"; + match "product" "0x2109"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0x0121"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x1016|0x1116|0x1216)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x1b1d|0x1e1d)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x2016|0x2116|0x2216|0x3016|0x3116|0x3216)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0x3524"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x4016|0x4116|0x4216|0x5016|0x5116|0x5216)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0x811c"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "0xca02"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0402"; + match "product" "0x5632"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0403"; + match "product" "(0x6001|0x6004|0x6010|0x6011|0x8372|0x9e90|0xcc48|0xcc49|0xcc4a|0xd678|0xe6c8|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xee18|0xf608|0xf60b|0xf850|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfc08|0xfc09|0xfc0b|0xfc0c|0xfc0d|0xfc82)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0408"; + match "product" "0x0304"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0408"; + match "product" "(0x1000|0xea02|0xea03|0xea04|0xea05|0xea06)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0409"; + match "product" "(0x00d5|0x00d6|0x00d7|0x8024|0x8025)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x0001|0x0005|0x0009)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x0012"; + action "kldload if_rue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x003d"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x005e|0x0066|0x0067)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x006e"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x008b"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x00b3"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x00d8|0x00d9)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x00da"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x00e8"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x0116|0x0119)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x012e"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "0x0137"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0411"; + match "product" "(0x0148|0x0150|0x015d|0x016f)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0413"; + match "product" "0x2101"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0423"; + match "product" "(0x000a|0x000c)"; + action "kldload if_cue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x043e"; + match "product" "0x9c01"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045a"; + match "product" "(0x5001|0x5002)"; + action "kldload urio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045b"; + match "product" "0x0053"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045e"; + match "product" "0x0079"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045e"; + match "product" "0x007a"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x045e"; + match "product" "(0x00ce|0x0400|0x0401|0x0402|0x0403|0x0404|0x0405|0x0406|0x0407|0x0408|0x0409|0x040a|0x040b|0x040c|0x040d|0x040e|0x040f|0x0410|0x0411|0x0412|0x0413|0x0414|0x0415|0x0416|0x0417|0x0432|0x0433|0x0434|0x0435|0x0436|0x0437|0x0438|0x0439|0x043a|0x043b|0x043c|0x043d|0x043e|0x043f|0x0440|0x0441|0x0442|0x0443|0x0444|0x0445|0x0446|0x0447|0x0448|0x0449|0x044a|0x044b|0x044c|0x044d|0x044e|0x044f|0x0450|0x0451|0x0452|0x0453|0x0454|0x0455|0x0456|0x0457|0x0458|0x0459|0x045a|0x045b|0x045c|0x045d|0x045e|0x045f|0x0460|0x0461|0x0462|0x0463|0x0464|0x0465|0x0466|0x0467|0x0468|0x0469|0x046a|0x046b|0x046c|0x046d|0x046e|0x046f|0x0470|0x0471|0x0472|0x0473|0x0474|0x0475|0x0476|0x0477|0x0478|0x0479|0x047a|0x047b|0x04c8|0x04c9|0x04ca|0x04cb|0x04cc|0x04cd|0x04ce|0x04d7|0x04d8|0x04d9|0x04da|0x04db|0x04dc|0x04dd|0x04de|0x04df|0x04e0|0x04e1|0x04e2|0x04e3|0x04e4|0x04e5|0x04e6|0x04e7|0x04e8|0x04e9|0x04ea)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0471"; + match "product" "0x066a"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0471"; + match "product" "0x1236"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0471"; + match "product" "0x200f"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0482"; + match "product" "0x0203"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0489"; + match "product" "(0xe000|0xe003)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x049f"; + match "product" "(0x0003|0x0032)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x049f"; + match "product" "0x505a"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a4"; + match "product" "0x0014"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a5"; + match "product" "0x4027"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04a5"; + match "product" "0x4068"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04ad"; + match "product" "(0x0301|0x0302|0x0303|0x0306)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b4"; + match "product" "0x1002"; + action "kldload ufm"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b7"; + match "product" "0x0531"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04b8"; + match "product" "(0x0521|0x0522)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "0x0901"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "(0x0904|0x0913)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "0x0930"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "(0x0944|0x0945|0x0947|0x0948)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bb"; + match "product" "(0x0a03|0x0a0e)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04bf"; + match "product" "(0x0115|0x0117)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04c5"; + match "product" "(0x1058|0x1079)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04da"; + match "product" "0x2500"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04da"; + match "product" "0x3900"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04dd"; + match "product" "(0x8004|0x8005|0x8006|0x8007|0x9031)"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04dd"; + match "product" "(0x9102|0x9121|0x9123|0x9151|0x91ac|0x9242)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "(0x5f00|0x5f01|0x5f02|0x5f03|0x5f04)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "0x6601"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "(0x6611|0x6613|0x6615|0x6617|0x6619|0x661b|0x662e|0x6630|0x6632)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04e8"; + match "product" "0x8001"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04f1"; + match "product" "0x3008"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x04f1"; + match "product" "(0x3011|0x3012)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0502"; + match "product" "(0x1631|0x1632|0x16e1|0x16e2|0x16e3)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0506"; + match "product" "(0x03e8|0x11f8)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0506"; + match "product" "0x4601"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0103"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0109"; + action "kldload umct"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0121"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0257"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x0409"; + action "kldload umct"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x1203"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x4050"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x5055"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x7050"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "(0x7050|0x7051)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x705a"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x705c"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x705e"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "(0x8053|0x805c|0x815c|0x825a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x905b"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x050d"; + match "product" "0x935a"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0525"; + match "product" "0x1080"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0525"; + match "product" "0xa4a2"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0536"; + match "product" "0x01a0"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0543"; + match "product" "(0x0ed9|0x1527|0x1529|0x152b|0x152e|0x1921|0x1922|0x1923)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0547"; + match "product" "0x2008"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0547"; + match "product" "0x2720"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x054c"; + match "product" "(0x0038|0x0066|0x0095|0x009a|0x00da|0x0169)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x054c"; + match "product" "0x0437"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2002"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2007"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2008"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x2009"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0557"; + match "product" "0x4000"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x055d"; + match "product" "0x2018"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0565"; + match "product" "0x0001"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0565"; + match "product" "(0x0002|0x0003|0x0005)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0567"; + match "product" "(0x2000|0x2002)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056c"; + match "product" "0x8007"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "(0x200c|0x4002|0x4005|0x400b|0x4010)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "(0x5003|0x5004)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x056e"; + match "product" "0xabc1"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x057c"; + match "product" "(0x2200|0x3800)"; + action "kldload ng_ubt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0584"; + match "product" "0xb000"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0584"; + match "product" "0xb020"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0586"; + match "product" "(0x3401|0x3407|0x3409|0x340a|0x340f|0x3410)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0586"; + match "product" "(0x3416|0x341a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x058f"; + match "product" "0x9720"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05a6"; + match "product" "0x0101"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "(0x020d|0x020e|0x020f|0x0215|0x0217|0x0218|0x0219|0x021a|0x021b|0x021c|0x0229|0x022a|0x022b|0x030a|0x030b)"; + action "kldload atp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ac"; + match "product" "0x1402"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05ad"; + match "product" "0x0fba"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05c6"; + match "product" "(0x6000|0x6613)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05cc"; + match "product" "0x3000"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05db"; + match "product" "(0x0003|0x0005|0x0009|0x000a|0x0011)"; + action "kldload uvscom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e0"; + match "product" "(0x2000|0x2001|0x2002|0x2003|0x2004|0x2005|0x2006|0x2007|0x2008|0x2009|0x200a)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e3"; + match "product" "0x0501"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x05e9"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x066b"; + match "product" "(0x200c|0x2202)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x066b"; + match "product" "0x2202"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x066b"; + match "product" "(0x2203|0x2204|0x2206|0x400b)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0675"; + match "product" "0x0550"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "(0x0000|0x0001)"; + action "kldload udbp"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "(0x04bb|0x0609|0x0611|0x0612|0x1234|0x206a|0x2303)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "0x2501"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067b"; + match "product" "(0x331a|0xaaa0|0xaaa2)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067c"; + match "product" "0x1001"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x067e"; + match "product" "0x1001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0681"; + match "product" "0x3c06"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06e1"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06f8"; + match "product" "0xe000"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06f8"; + match "product" "(0xe010|0xe020)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x06f8"; + match "product" "0xe030"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "0x0100"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "(0x0200|0x0201)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "0xee13"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0707"; + match "product" "0xee13"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0711"; + match "product" "(0x0200|0x0210|0x0230)"; + action "kldload umct"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0731"; + match "product" "(0x0528|0x2003)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0745"; + match "product" "0x0001"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0745"; + match "product" "0x1000"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0769"; + match "product" "0x11f2"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0769"; + match "product" "0x11f3"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0769"; + match "product" "0x31f3"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x077b"; + match "product" "0x2226"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0789"; + match "product" "0x010c"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0789"; + match "product" "0x0160"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0789"; + match "product" "(0x0162|0x0163|0x0164)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x078b"; + match "product" "0x1234"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x079b"; + match "product" "0x0027"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x079b"; + match "product" "(0x004a|0x0062)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07a6"; + match "product" "(0x07c2|0x0986|0x8511|0x8513|0x8515)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x0001"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "(0x0004|0x000d)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x0017"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x002a"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "(0x002d|0x002e)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "(0x002f|0x003c|0x003f|0x0041|0x0042)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07aa"; + match "product" "0x9601"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0x110c|0x200c)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0x2770|0x2870|0x3070|0x3071|0x3072)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0x4000"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0x4002|0x4003|0x4004|0x4007|0x400b|0x400c|0x4102|0x4104)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0x420a"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0x6001"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "0xabc1"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07b8"; + match "product" "(0xb21b|0xb21c|0xb21d|0xb21e|0xb21f)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07c9"; + match "product" "0xb100"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07cf"; + match "product" "(0x2001|0x2002|0x2003)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07d1"; + match "product" "0x3a0c"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07d1"; + match "product" "(0x3c03|0x3c04|0x3c06|0x3c07)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x07d1"; + match "product" "(0x3c09|0x3c0a|0x3c0b|0x3c0d|0x3c0e|0x3c0f|0x3c11|0x3c13|0x3c15|0x3c16)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x081e"; + match "product" "0xdf00"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x082d"; + match "product" "(0x0100|0x0200|0x0300)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0830"; + match "product" "(0x0001|0x0002|0x0003|0x0020|0x0031|0x0040|0x0050|0x0060|0x0061|0x0070)"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0833"; + match "product" "(0x012e|0x039f)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x1046"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4506"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4506"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4508"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x4521"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0x5046"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "(0x6618|0x7511|0x7512|0x7522|0x8522|0xa512|0xa618|0xa701|0xa702|0xb522|0xc522|0xd522)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x083a"; + match "product" "0xe501"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0841"; + match "product" "0x0001"; + action "kldload urio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "(0x1001|0x1002)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x1020"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x1040"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x4240"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x4260"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "0x4300"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0846"; + match "product" "(0x6100|0x6a00)"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0856"; + match "product" "0xac01"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x085a"; + match "product" "(0x0008|0x0009)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x086e"; + match "product" "0x1920"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x087d"; + match "product" "0x5704"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08d1"; + match "product" "0x0001"; + action "kldload if_cue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08d1"; + match "product" "0x0003"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08dd"; + match "product" "(0x0986|0x0987|0x0988|0x8511)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08dd"; + match "product" "0x90ff"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08e6"; + match "product" "0x5501"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x08fd"; + match "product" "0x000a"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0915"; + match "product" "(0x2000|0x2002)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x091e"; + match "product" "0x0004"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0921"; + match "product" "0x1001"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0930"; + match "product" "(0x0700|0x0705|0x0706|0x0707|0x0708|0x0709|0x070a|0x070b)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0930"; + match "product" "0x0a07"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0930"; + match "product" "(0x0d45|0x1302)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x093c"; + match "product" "(0x0601|0x0701)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x094b"; + match "product" "0x0001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0951"; + match "product" "0x0008"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0951"; + match "product" "0x000a"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x095a"; + match "product" "0x3003"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0960"; + match "product" "(0x0065|0x0066|0x0067)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0961"; + match "product" "0x0010"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x099e"; + match "product" "(0x0052|0x4000)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x09aa"; + match "product" "0x1000"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x09d7"; + match "product" "0x0100"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0a46"; + match "product" "(0x0268|0x8515|0x9601)"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0a5c"; + match "product" "0x2033"; + action "kldload ubtbcmfw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0ace"; + match "product" "(0x1211|0x1215)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x5000|0x6000|0x6050|0x6100|0x6150|0x6200|0x6250|0x6300|0x6350|0x6500|0x6501|0x6600|0x6601|0x6701|0x6721|0x6741|0x6761|0x6800|0x6901)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x6911"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x6971"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x6971"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x7001"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x7011"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x7021|0x7041|0x7061|0x7100|0x7201|0x7211)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x7251|0x7301|0x7361|0x7381|0x7401|0x7501)"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0x7601"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0x7601|0xc031|0xd013|0xd031)"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "0xd033"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0af0"; + match "product" "(0xd033|0xd055|0xd055)"; + action "kldload uhso"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x1706|0x1707)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x170c|0x171b)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "0x171d"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x1723|0x1724)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x1731|0x1732|0x1742|0x1760|0x1761|0x1784|0x1790)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "(0x4200|0x4201|0x4202|0x420f|0x9200|0x9202)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b39"; + match "product" "0x0109"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b39"; + match "product" "0x0421"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b3b"; + match "product" "(0x1630|0x5630|0x6630)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b41"; + match "product" "0x0011"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b63"; + match "product" "0x6530"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b8c"; + match "product" "0x2303"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b95"; + match "product" "(0x1720|0x1780|0x7720|0x772a)"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0baf"; + match "product" "0x0118"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0baf"; + match "product" "0x0121"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bb2"; + match "product" "0x6098"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bb4"; + match "product" "(0x00ce|0x00cf|0x00cf|0x0a01|0x0a02|0x0a03|0x0a04|0x0a05|0x0a06|0x0a07|0x0a08|0x0a09|0x0a0a|0x0a0b|0x0a0c|0x0a0d|0x0a0e|0x0a0f|0x0a10|0x0a11|0x0a12|0x0a13|0x0a14|0x0a15|0x0a16|0x0a17|0x0a18|0x0a19|0x0a1a|0x0a1b|0x0a1c|0x0a1d|0x0a1e|0x0a1f|0x0a20|0x0a21|0x0a22|0x0a23|0x0a24|0x0a25|0x0a26|0x0a27|0x0a28|0x0a29|0x0a2a|0x0a2b|0x0a2c|0x0a2d|0x0a2e|0x0a2f|0x0a30|0x0a31|0x0a32|0x0a33|0x0a34|0x0a35|0x0a36|0x0a37|0x0a38|0x0a39|0x0a3a|0x0a3b|0x0a3c|0x0a3d|0x0a3e|0x0a3f|0x0a40|0x0a41|0x0a42|0x0a43|0x0a44|0x0a45|0x0a46|0x0a47|0x0a48|0x0a49|0x0a4a|0x0a4b|0x0a4c|0x0a4d|0x0a4e|0x0a4f|0x0a50|0x0a51|0x0a52|0x0a53|0x0a54|0x0a55|0x0a56|0x0a57|0x0a58|0x0a59|0x0a5a|0x0a5b|0x0a5c|0x0a5d|0x0a5e|0x0a5f|0x0a60|0x0a61|0x0a62|0x0a63|0x0a64|0x0a65|0x0a66|0x0a67|0x0a68|0x0a69|0x0a6a|0x0a6b|0x0a6c|0x0a6d|0x0a6e|0x0a6f|0x0a70|0x0a71|0x0a72|0x0a73|0x0a74|0x0a75|0x0a76|0x0a77|0x0a78|0x0a79|0x0a7a|0x0a7b|0x0a7c|0x0a7d|0x0a7e|0x0a7f|0x0a80|0x0a81|0x0a82|0x0a83|0x0a84|0x0a85|0x0a86|0x0a87|0x0a88|0x0a89|0x0a8a|0x0a8b|0x0a8c|0x0a8d|0x0a8e|0x0a8f|0x0a90|0x0a91|0x0a92|0x0a93|0x0a94|0x0a95|0x0a96|0x0a97|0x0a98|0x0a99|0x0a9a|0x0a9b|0x0a9c|0x0a9d|0x0a9e|0x0a9f|0x0bce)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bda"; + match "product" "0x8150"; + action "kldload if_rue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bda"; + match "product" "(0x8187|0x8189|0x8197|0x8198)"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bed"; + match "product" "(0x1100|0x1101)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bf8"; + match "product" "0x1001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bf8"; + match "product" "0x1009"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c44"; + match "product" "0x03a2"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c88"; + match "product" "0x17da"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c88"; + match "product" "0x17da"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c88"; + match "product" "0x180a"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0c8e"; + match "product" "0x6000"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cad"; + match "product" "0x9001"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0008"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0011"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0012"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x0015"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "0x001a"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cde"; + match "product" "(0x0022|0x0025)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0cf3"; + match "product" "(0x0001|0x0003|0x0005)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0d8e"; + match "product" "0x3762"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0d8e"; + match "product" "(0x7801|0x7811)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x3820|0x3821|0x3822|0x3870|0x3871)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x6861|0x6865|0x6869)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x6874|0x6877)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0x6899|0x821a|0x822a|0x870a|0x871a|0x899a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db0"; + match "product" "(0xa861|0xa874)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0db7"; + match "product" "0x0002"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x000d"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x0017"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x0021"; + action "kldload if_mos"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x0028"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "(0x002b|0x002c|0x002d|0x0039|0x003b|0x003c|0x003d|0x003e|0x003f|0x0040|0x0041|0x0042|0x0047|0x0048|0x004a|0x004d)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x061c"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "(0x9071|0x9075)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "(0x90ac|0x9712)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df7"; + match "product" "0x0620"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e0b"; + match "product" "(0x9031|0x9041)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e55"; + match "product" "0x110b"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e66"; + match "product" "(0x0001|0x0003|0x0009|0x000b)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e66"; + match "product" "0x400c"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e67"; + match "product" "0x0002"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0e7e"; + match "product" "0x1001"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0ea0"; + match "product" "0x6858"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eab"; + match "product" "0xc893"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eb0"; + match "product" "0x9020"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eb0"; + match "product" "0x9021"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eba"; + match "product" "(0x1080|0x2080)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0eef"; + match "product" "(0x0001|0x0002)"; + action "kldload uep"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f3d"; + match "product" "0x0112"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f3d"; + match "product" "0x0112"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f4e"; + match "product" "0x0200"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f88"; + match "product" "0x3012"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f88"; + match "product" "0x3014"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f94"; + match "product" "0x0001"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0f98"; + match "product" "0x0201"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fb8"; + match "product" "(0x3001|0x3002|0x3003|0x4001)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fcf"; + match "product" "(0x1003|0x1004|0x1006)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0fe6"; + match "product" "(0x8101|0x9700)"; + action "kldload if_udav"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x100d"; + match "product" "(0x9031|0x9032)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1011"; + match "product" "0x3198"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "0x8001"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "0x8002"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "0x8007"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "(0x8008|0x800a)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1044"; + match "product" "(0x800b|0x800c|0x800d)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1066"; + match "product" "(0x00ce|0x0300|0x0500|0x0600|0x0700)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x106c"; + match "product" "0x3701"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10a6"; + match "product" "0xaa26"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10ab"; + match "product" "0x10c5"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10b5"; + match "product" "0xac70"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10b5"; + match "product" "0xac70"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10bd"; + match "product" "0x1427"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c4"; + match "product" "(0x0f91|0x1101|0x1601|0x800a|0x803b|0x8043|0x8044)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c4"; + match "product" "0x8053"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c4"; + match "product" "(0x8066|0x806f|0x807a|0x80ca|0x80dd|0x80ed|0x80f6|0x8115|0x813d|0x813f|0x814a|0x814a|0x814b|0x8156|0x815e|0x818b|0x819f|0x81a6|0x81ac|0x81ad|0x81c8|0x81e2|0x81e7|0x81e8|0x81f2|0x8218|0x822b|0x826b|0x8293|0x82f9|0x8341|0x8382|0x83a8|0x8411|0x846e|0x8477|0xea60|0xea61|0xea71|0xf001|0xf002|0xf003|0xf004)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10c5"; + match "product" "0xea61"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x10ce"; + match "product" "0xea61"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1114"; + match "product" "(0x0001|0x0004|0x0006)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x114b"; + match "product" "0x0110"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x114b"; + match "product" "0x0150"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1163"; + match "product" "0x0100"; + action "kldload ucycom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1182"; + match "product" "0x1388"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1186"; + match "product" "0x3e04"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1189"; + match "product" "0x0893"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1199"; + match "product" "(0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0112|0x0120|0x0218)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1199"; + match "product" "0x0218"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1199"; + match "product" "(0x0220|0x0224|0x0fff|0x6802|0x6803|0x6804|0x6805|0x6808|0x6809|0x6812|0x6813|0x6815|0x6816|0x6820|0x6821|0x6822|0x6832|0x6833|0x6834|0x6835|0x6838|0x6839|0x683a|0x683b|0x683c|0x683d|0x683e|0x6850|0x6851|0x6852|0x6853|0x6855|0x6856|0x6859|0x685a|0x6880|0x6890|0x6891|0x6892|0x6893|0x68a3)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11ad"; + match "product" "0x0701"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11d9"; + match "product" "(0x1002|0x1003)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f5"; + match "product" "(0x0001|0x0003|0x0004|0x0005)"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f6"; + match "product" "0x2001"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x11f7"; + match "product" "0x02df"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1231"; + match "product" "(0xce01|0xce02)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x126f"; + match "product" "0xa006"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x129b"; + match "product" "0x1666"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x129b"; + match "product" "0x1828"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1465|0x14ac|0x1520)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12ef"; + match "product" "0x0100"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1342"; + match "product" "0x0204"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1371"; + match "product" "(0x9022|0x9032)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1371"; + match "product" "0x9401"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1385"; + match "product" "(0x4250|0x5f00|0x5f02)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13ad"; + match "product" "0x9999"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x000c"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "(0x000d|0x0011)"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x0018"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x001a"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "(0x0020|0x0023)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13b1"; + match "product" "0x0024"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13d2"; + match "product" "0x0400"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x13d3"; + match "product" "(0x3247|0x3262|0x3273|0x3284|0x3305)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1410"; + match "product" "(0x1100|0x1110|0x1120|0x1130|0x1400|0x1410|0x1420|0x1430|0x1450|0x2100|0x2110|0x2120|0x2130|0x2400|0x2410|0x2420|0x4100|0x4400|0x5010|0x5100|0x6000|0x6002|0x7042)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1416"; + match "product" "0x1110"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1435"; + match "product" "0x0427"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1435"; + match "product" "0x0711"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1435"; + match "product" "(0x0826|0x082a)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1453"; + match "product" "0x4026"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1472"; + match "product" "0x0009"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1482"; + match "product" "0x3c09"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1485"; + match "product" "(0x0001|0x0002)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x1706"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x2070"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x2570"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "(0x2573|0x2671)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "(0x2770|0x2870|0x3070|0x3071|0x3072|0x3370|0x3572|0x8070)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x9020"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x148f"; + match "product" "0x9021"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "0x3c02"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "(0x3c06|0x3c07|0x3c08|0x3c09|0x3c11|0x3c12)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "0x3c22"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14b2"; + match "product" "(0x3c23|0x3c25|0x3c25|0x3c27|0x3c28)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14ea"; + match "product" "0xab10"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14ea"; + match "product" "0xab11"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x14ea"; + match "product" "0xab13"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1555"; + match "product" "0x0004"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1557"; + match "product" "0x7720"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1557"; + match "product" "0x8150"; + action "kldload if_rue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x3006"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "(0x300a|0x300b|0x300d)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x300e"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x3204"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x157e"; + match "product" "0x3205"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1582"; + match "product" "0x6003"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15a9"; + match "product" "0x0004"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15a9"; + match "product" "(0x0006|0x0010)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15c5"; + match "product" "0x0008"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x15e8"; + match "product" "(0x9100|0x9110)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1614"; + match "product" "(0x0800|0x0802|0x7002)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1631"; + match "product" "0x6200"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1631"; + match "product" "0xc019"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1645"; + match "product" "(0x0005|0x0008|0x8005)"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x166a"; + match "product" "0x0303"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x167b"; + match "product" "0x4001"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x168c"; + match "product" "0x0001"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "0x0601"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "(0x0710|0x0712)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "0x0722"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1690"; + match "product" "(0x0740|0x0744)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16ab"; + match "product" "(0x7801|0x7811)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "(0x6202|0x6501)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "0x6501"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "0x6502"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d5"; + match "product" "0x6502"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d6"; + match "product" "(0x0001|0x0001)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d8"; + match "product" "(0x6006|0x6280)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16d8"; + match "product" "0x6280"; + action "kldload ugensa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x16dc"; + match "product" "(0x0010|0x0011|0x0012|0x0015)"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1726"; + match "product" "0x1000"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1726"; + match "product" "0x1000"; + action "kldload ubsa"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "0x0039"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "(0x0070|0x0071)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "0x0073"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1737"; + match "product" "(0x0077|0x0078|0x0079)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1740"; + match "product" "(0x0605|0x0615)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1740"; + match "product" "0x2000"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1740"; + match "product" "(0x9701|0x9702|0x9703|0x9705|0x9706|0x9707|0x9708|0x9709|0x9801)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1761"; + match "product" "0x0b05"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x177f"; + match "product" "(0x0153|0x0302|0x0313)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x17f4"; + match "product" "0xaaaa"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1843"; + match "product" "0x0200"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18c5"; + match "product" "0x0002"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18c5"; + match "product" "(0x0008|0x0012)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "(0x6196|0x6229)"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "0x6232"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "0x6238"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18e8"; + match "product" "0x6259"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x18ef"; + match "product" "0xe00f"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x19d2"; + match "product" "(0x0001|0x0002|0x0003|0x0004|0x0005|0x0006|0x0007|0x0008|0x0009|0x000a|0x000b|0x000c|0x000d|0x000e|0x000f|0x0010|0x0011|0x0012|0x0013|0x0014|0x0015|0x0016|0x0017|0x0018|0x0019|0x0020|0x0021|0x0022|0x0023|0x0024|0x0025|0x0026|0x0027|0x0028|0x0029|0x0030|0x0031|0x0032|0x0033|0x0037|0x0039|0x0042|0x0043|0x0048|0x0049|0x0051|0x0052|0x0053|0x0054|0x0055|0x0057|0x0058|0x0059|0x0060|0x0061|0x0062|0x0063|0x0064|0x0066|0x0069|0x0070|0x0073|0x0076|0x0078|0x0082|0x0086|0x0117|0x2000|0x2002|0x2003|0xfff1|0xfff5|0xfffe)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1a86"; + match "product" "0x7523"; + action "kldload uchcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1a8d"; + match "product" "(0x1002|0x1003|0x1004|0x1005|0x1006|0x1007|0x1008|0x1009|0x100a|0x100b|0x100c|0x100d|0x100e|0x100f|0x1010|0x1011|0x1012)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b3d"; + match "product" "0x0153"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b75"; + match "product" "0x3072"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1b75"; + match "product" "0x8187"; + action "kldload if_urtw"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1bbb"; + match "product" "(0x0000|0xf000)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1bc7"; + match "product" "(0x1003|0x1004)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1be3"; + match "product" "0x07a6"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1c9e"; + match "product" "(0x6061|0x9603|0xf000)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1cf1"; + match "product" "(0x0001|0x0004)"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1d09"; + match "product" "0x4000"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1d4d"; + match "product" "(0x0002|0x000c|0x000e|0x0010)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1da5"; + match "product" "(0x4512|0x4515|0x4519|0x4523)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1e0e"; + match "product" "(0x9000|0x9200|0xce16)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1eda"; + match "product" "0x2310"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x1a00"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x200c"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "(0x3a00|0x3a02|0x3a04)"; + action "kldload if_uath"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x3c00"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x3c05"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "(0x3c09|0x3c0a)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x4000"; + action "kldload if_kue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "(0x4001|0x4002|0x4003|0x400b|0x4102|0xabc1)"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0x5303"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0xab01"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "(0xab24|0xab25)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0xab50"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "(0xc007|0xed01)"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "0xed02"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2019"; + match "product" "(0xed06|0xed14)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x203d"; + match "product" "(0x1480|0x14a1|0x14a9)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20b8"; + match "product" "0x8888"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x20b9"; + match "product" "0x1682"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x22b8"; + match "product" "(0x4204|0x4214|0x4224|0x4234|0x4244)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x22b8"; + match "product" "(0x600c|0x6027)"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2478"; + match "product" "0x2008"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3334"; + match "product" "0x1701"; + action "kldload if_aue"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3340"; + match "product" "(0x011c|0x0326|0x0426|0x043a|0x051c|0x053a|0x071c|0x0b1c|0x0e3a|0x0f1c|0x0f3a|0x1326|0x191c|0x2326|0x3326)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x3708"; + match "product" "(0x20ce|0x21ce)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4113"; + match "product" "(0x0210|0x0211|0x0400|0x0410)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "(0x4001|0x4002|0x4003|0x4004|0x4005|0x4006|0x4007|0x4008|0x4009)"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "(0x8102|0x8104)"; + action "kldload if_upgt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "(0x8114|0x8115|0x8116|0x8117|0x8118|0x8128|0x8129|0x8133|0x8134|0x8135|0x8136|0x8137|0x8138|0x8180|0x8181|0x8182)"; + action "kldload u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x413c"; + match "product" "0x9500"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4348"; + match "product" "0x5523"; + action "kldload uchcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4505"; + match "product" "0x0010"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x4766"; + match "product" "0x0001"; + action "kldload uvisor"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5173"; + match "product" "0x1809"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5372"; + match "product" "0x2303"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5a57"; + match "product" "0x0260"; + action "kldload if_ural"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5a57"; + match "product" "(0x0280|0x0282|0x0283|0x0284|0x5257)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x5e04"; + match "product" "0xce00"; + action "kldload uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6189"; + match "product" "0x182d"; + action "kldload if_axe"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6189"; + match "product" "0x2068"; + action "kldload uplcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6547"; + match "product" "0x0232"; + action "kldload uark"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x6891"; + match "product" "0xa727"; + action "kldload if_zyd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x7392"; + match "product" "0x7318"; + action "kldload if_rum"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x7392"; + match "product" "(0x7711|0x7717|0x7718)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x8516"; + match "product" "(0x2070|0x2770|0x2870|0x3070|0x3071|0x3072|0x3572)"; + action "kldload if_run"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7703"; + action "kldload umoscom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7730"; + action "kldload if_mos"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7820"; + action "kldload umcs"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7830"; + action "kldload if_mos"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9710"; + match "product" "0x7840"; + action "kldload umcs"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x9e88"; + match "product" "0x9e8f"; + action "kldload uftdi"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0xdaae"; + match "product" "0xead6"; + action "kldload uslcom"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x02"; + match "intprotocol" "0x01"; + action "kldload umodem"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ukbd"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + match "intsubclass" "0x01"; + match "intprotocol" "0x02"; + action "kldload ums"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x02"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x07"; + match "intsubclass" "0x01"; + match "intprotocol" "0x03"; + action "kldload ulpt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0xe0"; + match "intsubclass" "0x01"; + match "intprotocol" "0x01"; + action "kldload ng_ubt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0xff"; + match "intsubclass" "0x5d"; + match "intprotocol" "0x01"; + action "kldload uhid"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x01"; + match "intsubclass" "0x01"; + action "kldload snd_uaudio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x01"; + match "intsubclass" "0x03"; + action "kldload snd_uaudio"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x06"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x0a"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "(host|device)"; + match "intclass" "0x02"; + match "intsubclass" "0x0d"; + action "kldload if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x02"; + match "intsubclass" "0x88"; + action "kldload ufoma"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x03"; + action "kldload uhid"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "intclass" "0x08"; + action "kldload umass"; +}; + +# 1634 USB entries processed + -- cgit v1.1 From 985a8017af3f68f5334fc6e5dd798b35f87d9846 Mon Sep 17 00:00:00 2001 From: marcel Date: Sat, 25 Jun 2011 17:58:35 +0000 Subject: Oops. The sec field of struct bintime is *not* a 32-bit type. It's time_t, which is 64 bits on ia64. --- sys/ia64/ia64/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index 74b2248..96d07c4 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -185,7 +185,7 @@ clock_configure(void *dummy) et->et_frequency = itc_freq; et->et_min_period.sec = 0; et->et_min_period.frac = (0x8000000000000000ul / (u_long)(10*hz)) << 1; - et->et_max_period.sec = ~0ul; /* XXX unless itc_freq >= (1<<32) */ + et->et_max_period.sec = 0xffffffff; et->et_max_period.frac = ((0xfffffffeul << 32) / itc_freq) << 32; et->et_start = ia64_clock_start; et->et_stop = ia64_clock_stop; -- cgit v1.1 From 35ba8ced5b0491e06a685303911bfc005dc85ace Mon Sep 17 00:00:00 2001 From: joel Date: Sat, 25 Jun 2011 19:21:54 +0000 Subject: More accurate birthplace. --- usr.bin/calendar/calendars/calendar.freebsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd index 957dafd..bf15da7 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -289,7 +289,7 @@ 10/18 Sheldon Hearn born in Cape Town, Western Cape, South Africa, 1974 10/19 Nicholas Souchu born in Suresnes, Hauts-de-Seine, France, 1972 10/19 Nick Barkas born in Longview, Washington, United States, 1981 -10/20 Joel Dahl born in Lidkoping, Sweden, 1983 +10/20 Joel Dahl born in Bitterna, Skaraborg, Sweden, 1983 10/20 Dmitry Marakasov born in Moscow, Russian Federation, 1984 10/21 Ben Smithurst born in Sheffield, South Yorkshire, United Kingdom, 1981 10/22 Jean-Sebastien Pedron born in Redon, Ille-et-Vilaine, France, 1980 -- cgit v1.1 From e836f024cab4f558654df4b50e35acaeb14c802f Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 25 Jun 2011 20:37:43 +0000 Subject: sh: Test that '!' is literal if quoted and first char of bracket expression This also works on stable/8. --- tools/regression/bin/sh/builtins/case10.0 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tools/regression/bin/sh/builtins/case10.0 diff --git a/tools/regression/bin/sh/builtins/case10.0 b/tools/regression/bin/sh/builtins/case10.0 new file mode 100644 index 0000000..a627b5c --- /dev/null +++ b/tools/regression/bin/sh/builtins/case10.0 @@ -0,0 +1,16 @@ +# $FreeBSD$ + +case ! in +[\!!]) ;; +*) echo Failed at $LINENO ;; +esac + +case ! in +['!'!]) ;; +*) echo Failed at $LINENO ;; +esac + +case ! in +["!"!]) ;; +*) echo Failed at $LINENO ;; +esac -- cgit v1.1 From a6b7f1b6f8741f37941684e939365056b5b10d0d Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Sun, 26 Jun 2011 00:35:11 +0000 Subject: Do not attach to the sound device on G5 Xserves, which is actually an LED controller used to run the load graph on the server's front panel. Reported by: Paul Mather MFC after: 3 days --- sys/dev/sound/macio/i2s.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sys/dev/sound/macio/i2s.c b/sys/dev/sound/macio/i2s.c index d1a5463..e35a262 100644 --- a/sys/dev/sound/macio/i2s.c +++ b/sys/dev/sound/macio/i2s.c @@ -158,6 +158,8 @@ static int i2s_probe(device_t self) { const char *name; + phandle_t subchild; + char subchildname[255]; name = ofw_bus_get_name(self); if (!name) @@ -165,6 +167,16 @@ i2s_probe(device_t self) if (strcmp(name, "i2s") != 0) return (ENXIO); + + /* + * Do not attach to "lightshow" I2S devices on Xserves. This controller + * is used there to control the LEDs on the front panel, and this + * driver can't handle it. + */ + subchild = OF_child(OF_child(ofw_bus_get_node(self))); + if (subchild != 0 && OF_getprop(subchild, "name", subchildname, + sizeof(subchildname)) > 0 && strcmp(subchildname, "lightshow") == 0) + return (ENXIO); device_set_desc(self, "Apple I2S Audio Controller"); -- cgit v1.1 From 5bdade59d5393bbe13facdf0be4318c4e86c46dd Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Sun, 26 Jun 2011 00:49:17 +0000 Subject: Turn the minimum PWM fan speed down to 30 from 40. It turns out the burning smell that caused me to turn this up was due to a failed fan burning, not a CPU (plus a healthy dose of paranoia). Submitted by: Paul Mather --- sys/powerpc/powermac/fcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/powerpc/powermac/fcu.c b/sys/powerpc/powermac/fcu.c index 7ac9b1b..eb43ff2 100644 --- a/sys/powerpc/powermac/fcu.c +++ b/sys/powerpc/powermac/fcu.c @@ -510,7 +510,7 @@ fcu_fill_fan_prop(device_t dev) sc->sc_fans[j].fan.set = (int (*)(struct pmac_fan *, int))(fcu_fan_set_rpm); } else { - sc->sc_fans[j].fan.min_rpm = 40; /* Percent */ + sc->sc_fans[j].fan.min_rpm = 30; /* Percent */ sc->sc_fans[j].fan.max_rpm = 100; sc->sc_fans[j].fan.read = NULL; sc->sc_fans[j].fan.set = -- cgit v1.1 From 1152c6dddc834f1d787357656082b676b62a4523 Mon Sep 17 00:00:00 2001 From: gibbs Date: Sun, 26 Jun 2011 01:14:54 +0000 Subject: cam/cam_xpt.c: In camisr_runqueue(), we need to run the sims queue regardless of whether or not the current peripheral has more work to do. This reverts a change mistakenly made in revision 223081. Reported by: ache --- sys/cam/cam_xpt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index f234076..013c415 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -4894,8 +4894,8 @@ camisr_runqueue(void *V_queue) && (--dev->tag_delay_count == 0)) xpt_start_tags(ccb_h->path); if (!device_is_send_queued(dev)) { - runq = xpt_schedule_dev_sendq(ccb_h->path->bus, - dev); + (void)xpt_schedule_dev_sendq(ccb_h->path->bus, + dev); } } -- cgit v1.1 From 59e398752aa5192e2f984e4cdd08479f181c9d18 Mon Sep 17 00:00:00 2001 From: gibbs Date: Sun, 26 Jun 2011 01:32:46 +0000 Subject: cam/scsi/scsi_cd.c: In cdregister(), hold the periph lock semaphore during changer probe/configuration. This removes a window where an open of the cd device may succeed before probe processing has completed. --- sys/cam/scsi/scsi_cd.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index c1951ff..91384b7 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -687,6 +687,10 @@ cdregister(struct cam_periph *periph, void *arg) else softc->minimum_command_size = 6; + /* + * Refcount and block open attempts until we are setup + * Can't block + */ (void)cam_periph_hold(periph, PRIBIO); cam_periph_unlock(periph); /* @@ -747,7 +751,6 @@ cdregister(struct cam_periph *periph, void *arg) softc->disk->d_hba_subdevice = cpi.hba_subdevice; disk_create(softc->disk, DISK_VERSION); cam_periph_lock(periph); - cam_periph_unhold(periph); /* * Add an async callback so that we get @@ -972,12 +975,6 @@ cdregister(struct cam_periph *periph, void *arg) cdregisterexit: - /* - * Refcount and block open attempts until we are setup - * Can't block - */ - (void)cam_periph_hold(periph, PRIBIO); - if ((softc->flags & CD_FLAG_CHANGER) == 0) xpt_schedule(periph, CAM_PRIORITY_DEV); else -- cgit v1.1 From e9575bd6c4a5847413878c742f7a34015fa13fe2 Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 26 Jun 2011 09:32:46 +0000 Subject: Replace tab with 8 spaces, bringing it in line with the rest of the file. --- etc/regdomain.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/etc/regdomain.xml b/etc/regdomain.xml index 5e98dea..d86df22 100644 --- a/etc/regdomain.xml +++ b/etc/regdomain.xml @@ -341,9 +341,9 @@ 0x30 - - 30 - IEEE80211_CHAN_B + + 30 + IEEE80211_CHAN_B -- cgit v1.1 From 827f99272dabff5cd65c603f41db85caa263b974 Mon Sep 17 00:00:00 2001 From: kevlo Date: Sun, 26 Jun 2011 10:07:48 +0000 Subject: Remove duplicate header includes --- sys/arm/at91/at91_machdep.c | 1 - sys/arm/sa11x0/assabet_machdep.c | 1 - sys/arm/sa11x0/sa11x0.c | 2 -- sys/mips/atheros/ar71xx_chip.c | 8 +++----- sys/mips/atheros/ar71xx_machdep.c | 8 +++----- sys/mips/atheros/ar71xx_ohci.c | 2 -- sys/mips/atheros/ar71xx_setup.c | 8 +++----- sys/mips/atheros/ar724x_chip.c | 8 +++----- sys/mips/atheros/ar91xx_chip.c | 8 +++----- sys/mips/mips/genassym.c | 1 - sys/mips/mips/trap.c | 4 ---- sys/mips/rmi/dev/xlr/rge.c | 2 -- sys/mips/rmi/fmn.c | 1 - sys/mips/rmi/iodi.c | 1 - sys/mips/sentry5/s5_machdep.c | 7 ++----- sys/mips/sibyte/sb_machdep.c | 2 -- 16 files changed, 17 insertions(+), 47 deletions(-) diff --git a/sys/arm/at91/at91_machdep.c b/sys/arm/at91/at91_machdep.c index 717e7c2..a7eb5f6 100644 --- a/sys/arm/at91/at91_machdep.c +++ b/sys/arm/at91/at91_machdep.c @@ -91,7 +91,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ #define KERNEL_PT_KERN 1 diff --git a/sys/arm/sa11x0/assabet_machdep.c b/sys/arm/sa11x0/assabet_machdep.c index 87788f0..61c5056 100644 --- a/sys/arm/sa11x0/assabet_machdep.c +++ b/sys/arm/sa11x0/assabet_machdep.c @@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/arm/sa11x0/sa11x0.c b/sys/arm/sa11x0/sa11x0.c index bfffe6a..7b83f95 100644 --- a/sys/arm/sa11x0/sa11x0.c +++ b/sys/arm/sa11x0/sa11x0.c @@ -58,7 +58,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -74,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include extern void sa11x0_activateirqs(void); diff --git a/sys/mips/atheros/ar71xx_chip.c b/sys/mips/atheros/ar71xx_chip.c index 4a489a1..7f9792f 100644 --- a/sys/mips/atheros/ar71xx_chip.c +++ b/sys/mips/atheros/ar71xx_chip.c @@ -27,11 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include -#include - -#include - #include "opt_ddb.h" #include @@ -50,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -61,6 +57,8 @@ __FBSDID("$FreeBSD$"); #include +#include + /* XXX these should replace the current definitions in ar71xxreg.h */ /* XXX perhaps an ar71xx_chip.h header file? */ #define AR71XX_PLL_REG_CPU_CONFIG AR71XX_PLL_CPU_BASE + 0x00 diff --git a/sys/mips/atheros/ar71xx_machdep.c b/sys/mips/atheros/ar71xx_machdep.c index 60e28a4..1789994 100644 --- a/sys/mips/atheros/ar71xx_machdep.c +++ b/sys/mips/atheros/ar71xx_machdep.c @@ -27,11 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include -#include - -#include - #include "opt_ddb.h" #include @@ -50,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -60,6 +56,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + extern char edata[], end[]; uint32_t ar711_base_mac[ETHER_ADDR_LEN]; diff --git a/sys/mips/atheros/ar71xx_ohci.c b/sys/mips/atheros/ar71xx_ohci.c index acccd85..bee353e 100644 --- a/sys/mips/atheros/ar71xx_ohci.c +++ b/sys/mips/atheros/ar71xx_ohci.c @@ -49,8 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - static int ar71xx_ohci_attach(device_t dev); static int ar71xx_ohci_detach(device_t dev); static int ar71xx_ohci_probe(device_t dev); diff --git a/sys/mips/atheros/ar71xx_setup.c b/sys/mips/atheros/ar71xx_setup.c index 0720d52..ce600e4 100644 --- a/sys/mips/atheros/ar71xx_setup.c +++ b/sys/mips/atheros/ar71xx_setup.c @@ -27,11 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include -#include - -#include - #include "opt_ddb.h" #include @@ -50,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -64,6 +60,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #define AR71XX_SYS_TYPE_LEN 128 static char ar71xx_sys_type[AR71XX_SYS_TYPE_LEN]; diff --git a/sys/mips/atheros/ar724x_chip.c b/sys/mips/atheros/ar724x_chip.c index 75c5b38..edd1a9ad 100644 --- a/sys/mips/atheros/ar724x_chip.c +++ b/sys/mips/atheros/ar724x_chip.c @@ -27,11 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include -#include - -#include - #include "opt_ddb.h" #include @@ -50,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -62,6 +58,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + static void ar724x_chip_detect_mem_size(void) { diff --git a/sys/mips/atheros/ar91xx_chip.c b/sys/mips/atheros/ar91xx_chip.c index 9cf60bc..6761e89 100644 --- a/sys/mips/atheros/ar91xx_chip.c +++ b/sys/mips/atheros/ar91xx_chip.c @@ -27,11 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include -#include - -#include - #include "opt_ddb.h" #include @@ -50,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -61,6 +57,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + static void ar91xx_chip_detect_mem_size(void) { diff --git a/sys/mips/mips/genassym.c b/sys/mips/mips/genassym.c index fd168bc..2cb046d 100644 --- a/sys/mips/mips/genassym.c +++ b/sys/mips/mips/genassym.c @@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index 35b8030..c800e71 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -91,10 +91,6 @@ __FBSDID("$FreeBSD$"); #include #endif -#include -#include - - #ifdef TRAP_DEBUG int trap_debug = 0; SYSCTL_INT(_machdep, OID_AUTO, trap_debug, CTLFLAG_RW, diff --git a/sys/mips/rmi/dev/xlr/rge.c b/sys/mips/rmi/dev/xlr/rge.c index 274a934..1af97c2 100644 --- a/sys/mips/rmi/dev/xlr/rge.c +++ b/sys/mips/rmi/dev/xlr/rge.c @@ -78,8 +78,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include #include diff --git a/sys/mips/rmi/fmn.c b/sys/mips/rmi/fmn.c index f7686cb..9a6c486 100644 --- a/sys/mips/rmi/fmn.c +++ b/sys/mips/rmi/fmn.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/mips/rmi/iodi.c b/sys/mips/rmi/iodi.c index 3c09984..8952fcd 100644 --- a/sys/mips/rmi/iodi.c +++ b/sys/mips/rmi/iodi.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include diff --git a/sys/mips/sentry5/s5_machdep.c b/sys/mips/sentry5/s5_machdep.c index 4491b93..134f05b 100644 --- a/sys/mips/sentry5/s5_machdep.c +++ b/sys/mips/sentry5/s5_machdep.c @@ -27,11 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include -#include - -#include - #include "opt_ddb.h" #include @@ -75,6 +70,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #ifdef CFE #include #endif diff --git a/sys/mips/sibyte/sb_machdep.c b/sys/mips/sibyte/sb_machdep.c index ac30451..b6d395f 100644 --- a/sys/mips/sibyte/sb_machdep.c +++ b/sys/mips/sibyte/sb_machdep.c @@ -27,8 +27,6 @@ #include __FBSDID("$FreeBSD$"); -#include - #include "opt_ddb.h" #include "opt_kdb.h" -- cgit v1.1 From 9766ec89c2c6b4a48a4245bc3e9135510ac8e078 Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 26 Jun 2011 10:32:09 +0000 Subject: Add a couple more frequency ranges to the FCC3 (FCC + DFS) regulatory domain. The frequency range 5490MHz -> 5710MHz was opened up sometime in 2009, but regdomain.xml wasn't updated. FCC reference: (Section 15.407): http://louise.hallikainen.org/FCC/FccRules/2009/15/407/ The hole between 5600-5650MHz is due to a request from Airports using a weather radar system which also utilises this range. The GIT commit explaining this hole in more detail can be found here: http://git.kernel.org/?p=linux/kernel/git/linville/wireless-regdb.git;a=commit;h=fcbf9225d56e82d9a4e506187d42285e76d81523 --- etc/mtree/BSD.include.dist | 2 ++ etc/regdomain.xml | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index f960c52..013551b 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -229,6 +229,8 @@ .. kadm5 .. + lib80211 + .. libmilter .. lwres diff --git a/etc/regdomain.xml b/etc/regdomain.xml index d86df22..677c749 100644 --- a/etc/regdomain.xml +++ b/etc/regdomain.xml @@ -144,6 +144,18 @@ IEEE80211_CHAN_DFS + + 20 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + + + 20 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + 23 IEEE80211_CHAN_PASSIVE @@ -196,6 +208,34 @@ IEEE80211_CHAN_DFS + + 20 + IEEE80211_CHAN_HT20 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + + + 20 + IEEE80211_CHAN_HT40 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + + + 20 + IEEE80211_CHAN_HT20 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + + + 20 + IEEE80211_CHAN_HT40 + IEEE80211_CHAN_PASSIVE + IEEE80211_CHAN_DFS + + 23 IEEE80211_CHAN_HT20 @@ -1644,6 +1684,16 @@ 40 20 IEEE80211_CHAN_A + + 5500 5580 + 20 20 + IEEE80211_CHAN_A + + + 5500 5580 + 40 20 + IEEE80211_CHAN_A + 5500 5620 20 20 @@ -1664,6 +1714,16 @@ 20 20 IEEE80211_CHAN_A + + 5660 5700 + 20 20 + IEEE80211_CHAN_A + + + 5660 5700 + 40 20 + IEEE80211_CHAN_A + 5725 5825 40 20 -- cgit v1.1 From 1c5a60f771db5ca54fa7e1946d4240e7fa0c1f89 Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 26 Jun 2011 10:34:01 +0000 Subject: I think 23dBm is the correct value to use here. CRDA uses 20dBm + 3dB max antenna gain; I believe net80211 doesn't take antenna gain into account and leaves it up to the driver to enforce. (ath_hal(4) certainly tries to do this.) --- etc/regdomain.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/etc/regdomain.xml b/etc/regdomain.xml index 677c749..9b40605 100644 --- a/etc/regdomain.xml +++ b/etc/regdomain.xml @@ -139,19 +139,19 @@ - 20 + 23 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS - 20 + 23 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS - 20 + 23 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS @@ -195,42 +195,42 @@ - 20 + 23 IEEE80211_CHAN_HT20 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS - 20 + 23 IEEE80211_CHAN_HT40 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS - 20 + 23 IEEE80211_CHAN_HT20 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS - 20 + 23 IEEE80211_CHAN_HT40 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS - 20 + 23 IEEE80211_CHAN_HT20 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS - 20 + 23 IEEE80211_CHAN_HT40 IEEE80211_CHAN_PASSIVE IEEE80211_CHAN_DFS -- cgit v1.1 From 1d169284e3cab5f4a13ee56c30c1d21f166855c2 Mon Sep 17 00:00:00 2001 From: gavin Date: Sun, 26 Jun 2011 11:37:24 +0000 Subject: The SMCWUSBG is a zyd(4) device, not an uath(4) device. Remove from the latter. It appears that the addition to uath(4) came in through PR kern/135009, which had tested another device, the SMCWUSBTG2, successfully with uath(4) and included the SMCWUSBG as it "has the same chipset". I can find no other evidence that these two do actually share the same chipset. Moreover, Linux treats the SMCWUSBG as a zyd(4) device also. This reverts r223537. Discussed with: hselasky, kevlo MFC after: 1 week --- etc/devd/uath.conf | 4 ++-- sys/dev/usb/wlan/if_uath.c | 1 - sys/dev/usb/wlan/if_zyd.c | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/etc/devd/uath.conf b/etc/devd/uath.conf index dc4019c..9f0cb93 100644 --- a/etc/devd/uath.conf +++ b/etc/devd/uath.conf @@ -3,13 +3,13 @@ # Atheros USB wireless network device specific devd events # Accton -# SMCWUSB-G and SMCWUSBT-G2 +# SMCWUSBT-G2 notify 100 { match "system" "USB"; match "subsystem" "DEVICE"; match "type" "ATTACH"; match "vendor" "0x083a"; - match "product" "(0x4505|0x4507)"; + match "product" "0x4507"; action "/usr/sbin/uathload -d /dev/$cdev"; }; diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index baff5de..328dc4f 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -169,7 +169,6 @@ enum { /* recognized device vendors/products */ static const STRUCT_USB_HOST_ID uath_devs[] = { #define UATH_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } - UATH_DEV(ACCTON, SMCWUSBG), UATH_DEV(ACCTON, SMCWUSBTG2), UATH_DEV(ATHEROS, AR5523), UATH_DEV(ATHEROS2, AR5523_1), diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index 4221c34..f8d905e 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -229,6 +229,7 @@ static const STRUCT_USB_HOST_ID zyd_devs[] = { ZYD_ZD1211_DEV(ZYXEL, ZYAIRG220), ZYD_ZD1211_DEV(ZYXEL, G200V2), /* ZYD_ZD1211B */ + ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG_NF), ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG), ZYD_ZD1211B_DEV(ACCTON, ZD1211B), ZYD_ZD1211B_DEV(ASUS, A9T_WIFI), -- cgit v1.1 From 5c01535c7c4aeafb7ba7768538315dca39fa182c Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 26 Jun 2011 13:43:15 +0000 Subject: Add ATH_ENABLE_DFS which enables the DFS flag so the DFS code can be tested. This doesn't at all actually do radar detection! It's just so developers who wish to test the net80211 DFS code can easily do so. Without this flag, the DFS channels are never marked DFS and thus the DFS stuff doesn't run. --- sys/conf/options | 3 ++- sys/dev/ath/if_ath.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/conf/options b/sys/conf/options index ee696a8..1ce30b1 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -773,7 +773,8 @@ ATH_TXBUF opt_ath.h ATH_RXBUF opt_ath.h ATH_DIAGAPI opt_ath.h ATH_TX99_DIAG opt_ath.h -ATH_ENABLE_11N opt_ah.h +ATH_ENABLE_11N opt_ath.h +ATH_ENABLE_DFS opt_ath.h # options for the Atheros hal AH_SUPPORT_AR5416 opt_ah.h diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index f3afc70..1bca5e4 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -528,6 +528,9 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ | IEEE80211_C_BGSCAN /* capable of bg scanning */ | IEEE80211_C_TXFRAG /* handle tx frags */ +#ifdef ATH_ENABLE_DFS + | IEEE80211_C_DFS /* Enable DFS radar detection */ +#endif ; /* * Query the hal to figure out h/w crypto support. -- cgit v1.1 From 46ff0e559ab79ebfbd80e88d8039edc881cfb02b Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 26 Jun 2011 13:53:24 +0000 Subject: Fix beacon transmission after a channel set. The DFS code was tickling the channel set directly whilst going through the state RUN -> CSA -> RUN. This only changed the channel; it didn't go via ath_reset(). However in this driver, a channel change always causes a chip reset, which resets the beacon timer configuration and interrupt setup. This meant that data would go out but as the beacon timers never fired, beacons would never be queued. The confusing part is that sometimes the state transition was RUN -> SCAN -> CAC -> RUN (with CSA being in there sometimes); going via SCAN would clear sc_beacons and thus the transition to RUN would reprogram beacon transmission. In case someone tries debugging why suspending a device currently beaconing (versus just RX'ing beacons which is what occurs in STA mode), add a silly comment which should hopefully land them at this commit message. The call to ath_hal_reset() will be clearing the beacon config and it may not be always reset. --- sys/dev/ath/if_ath.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 1bca5e4..9c534c8 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1290,6 +1290,8 @@ ath_resume(struct ath_softc *sc) HAL_GPIO_MUX_MAC_NETWORK_LED); ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon); } + + /* XXX beacons ? */ } void @@ -1592,6 +1594,12 @@ ath_init(void *arg) sc->sc_lastani = 0; sc->sc_lastshortcal = 0; sc->sc_doresetcal = AH_FALSE; + /* + * Beacon timers were cleared here; give ath_newstate() + * a hint that the beacon timers should be poked when + * things transition to the RUN state. + */ + sc->sc_beacons = 0; /* * Setup the hardware after reset: the key cache @@ -4468,6 +4476,19 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ath_chan_change(sc, chan); /* + * Reset clears the beacon timers; reset them + * here if needed. + */ + if (sc->sc_beacons) { /* restart beacons */ +#ifdef IEEE80211_SUPPORT_TDMA + if (sc->sc_tdma) + ath_tdma_config(sc, NULL); + else +#endif + ath_beacon_config(sc, NULL); + } + + /* * Re-enable interrupts. */ ath_hal_intrset(ah, sc->sc_imask); -- cgit v1.1 From 19f06d03447715735cf72299000ec43a2f3b495c Mon Sep 17 00:00:00 2001 From: adrian Date: Sun, 26 Jun 2011 14:29:49 +0000 Subject: .. this wasn't supposed to be committed! sorry. --- etc/mtree/BSD.include.dist | 2 -- 1 file changed, 2 deletions(-) diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 013551b..f960c52 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -229,8 +229,6 @@ .. kadm5 .. - lib80211 - .. libmilter .. lwres -- cgit v1.1 From a7d17981201bb7c35b2a46ada38b7a2d98ab4c5c Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Sun, 26 Jun 2011 15:08:14 +0000 Subject: Revert r223479. It is unnecessary and served only to slightly ameliorate some manifestations of the bug actually fixed in r223485. --- sys/powerpc/aim/trap_subr32.S | 2 -- sys/powerpc/aim/trap_subr64.S | 2 -- 2 files changed, 4 deletions(-) diff --git a/sys/powerpc/aim/trap_subr32.S b/sys/powerpc/aim/trap_subr32.S index f00020b..172150e 100644 --- a/sys/powerpc/aim/trap_subr32.S +++ b/sys/powerpc/aim/trap_subr32.S @@ -754,8 +754,6 @@ k_trap: /* Call C interrupt dispatcher: */ trapagain: addi %r3,%r1,8 - addi %r4,%r1,-4 /* Clear any existing reservations */ - stwcx. %r3,0,%r4 bl CNAME(powerpc_interrupt) .globl CNAME(trapexit) /* backtrace code sentinel */ CNAME(trapexit): diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S index 1ec8507..111d516 100644 --- a/sys/powerpc/aim/trap_subr64.S +++ b/sys/powerpc/aim/trap_subr64.S @@ -514,8 +514,6 @@ trapagain: lis %r3,tocbase@ha ld %r2,tocbase@l(%r3) addi %r3,%r1,48 - addi %r4,%r1,-8 /* Clear any existing reservations */ - stdcx. %r3,0,%r4 bl CNAME(powerpc_interrupt) nop -- cgit v1.1 From 173e40756b0a87ae6de3b59b385bd2738df7e4cf Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Sun, 26 Jun 2011 16:11:36 +0000 Subject: Add better error handling for RTAS calls. These can potentially cause machine checks (e.g. invalid PCI configuration cycles), but these can be caught and recovered from. This change also the RTAS PCI driver to work without modification as a replacement for the Grackle driver on Grackle-based Powermacs. --- sys/powerpc/ofw/rtas.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sys/powerpc/ofw/rtas.c b/sys/powerpc/ofw/rtas.c index 59692c9..66ce12f 100644 --- a/sys/powerpc/ofw/rtas.c +++ b/sys/powerpc/ofw/rtas.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -39,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -60,6 +62,8 @@ int rtascall(vm_offset_t callbuffer, uintptr_t rtas_privdat); extern uintptr_t rtas_entry; extern register_t rtasmsr; +int setfault(faultbuf); /* defined in locore.S */ + /* * After the VM is up, allocate RTAS memory and instantiate it */ @@ -188,6 +192,7 @@ int rtas_call_method(cell_t token, int nargs, int nreturns, ...) { vm_offset_t argsptr; + faultbuf env; va_list ap; struct { cell_t token; @@ -213,7 +218,19 @@ rtas_call_method(cell_t token, int nargs, int nreturns, ...) args.args_n_results[n] = va_arg(ap, cell_t); argsptr = rtas_real_map(&args, sizeof(args)); - result = rtascall(argsptr, rtas_private_data); + + /* Get rid of any stale machine checks that have been waiting. */ + __asm __volatile ("sync; isync"); + if (!setfault(env)) { + __asm __volatile ("sync"); + result = rtascall(argsptr, rtas_private_data); + __asm __volatile ("sync; isync"); + } else { + result = RTAS_HW_ERROR; + } + curthread->td_pcb->pcb_onfault = 0; + __asm __volatile ("sync"); + rtas_real_unmap(argsptr, &args, sizeof(args)); mtx_unlock(&rtas_mtx); -- cgit v1.1 From 63ee2d30481a6cfa0ebc55582ca3b122de4d53c1 Mon Sep 17 00:00:00 2001 From: kientzle Date: Sun, 26 Jun 2011 17:54:11 +0000 Subject: The --newer-than test should descend into old directories to look for new files. PR: bin/150890 Submitted by: Tobias Herre MFC after: 3 weeks --- usr.bin/tar/write.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c index 838dffb..9d9025a 100644 --- a/usr.bin/tar/write.c +++ b/usr.bin/tar/write.c @@ -752,6 +752,9 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) break; } + if (bsdtar->option_no_subdirs) + descend = 0; + /* * Are we about to cross to a new filesystem? */ @@ -764,7 +767,6 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) } else if (descend == 0) { /* We're not descending, so no need to check. */ } else if (bsdtar->option_dont_traverse_mounts) { - /* User has asked us not to cross mount points. */ descend = 0; } else { /* We're prepared to cross a mount point. */ @@ -791,8 +793,15 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) * In -u mode, check that the file is newer than what's * already in the archive; in all modes, obey --newerXXX flags. */ - if (!new_enough(bsdtar, name, st)) + if (!new_enough(bsdtar, name, st)) { + if (!descend) + continue; + if (bsdtar->option_interactive && + !yes("add '%s'", name)) + continue; + tree_descend(tree); continue; + } archive_entry_free(entry); entry = archive_entry_new(); @@ -868,8 +877,7 @@ write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path) !yes("add '%s'", name)) continue; - /* Note: if user vetoes, we won't descend. */ - if (descend && !bsdtar->option_no_subdirs) + if (descend) tree_descend(tree); /* -- cgit v1.1 From 59c238c6bed4c3688cd951c136e0cd48bc67c028 Mon Sep 17 00:00:00 2001 From: ed Date: Sun, 26 Jun 2011 18:25:10 +0000 Subject: Fix various whitespace inconsistencies in sys/teken. --- sys/teken/demo/teken_demo.c | 6 +++--- sys/teken/gensequences | 4 ++-- sys/teken/libteken/teken.3 | 2 +- sys/teken/teken.c | 2 +- sys/teken/teken_subr.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sys/teken/demo/teken_demo.c b/sys/teken/demo/teken_demo.c index 0700763..16bb4b7 100644 --- a/sys/teken/demo/teken_demo.c +++ b/sys/teken/demo/teken_demo.c @@ -88,7 +88,7 @@ printchar(const teken_pos_t *p) getyx(stdscr, y, x); - px = &buffer[p->tp_col][p->tp_row]; + px = &buffer[p->tp_col][p->tp_row]; /* Convert Unicode to UTF-8. */ if (px->c < 0x80) { @@ -169,10 +169,10 @@ test_copy(void *s __unused, const teken_rect_t *r, const teken_pos_t *p) * Copying is a little tricky. We must make sure we do it in * correct order, to make sure we don't overwrite our own data. */ - + nrow = r->tr_end.tp_row - r->tr_begin.tp_row; ncol = r->tr_end.tp_col - r->tr_begin.tp_col; - + if (p->tp_row < r->tr_begin.tp_row) { /* Copy from top to bottom. */ if (p->tp_col < r->tr_begin.tp_col) { diff --git a/sys/teken/gensequences b/sys/teken/gensequences index 86c7979..e0fccd4 100644 --- a/sys/teken/gensequences +++ b/sys/teken/gensequences @@ -3,7 +3,7 @@ #- # Copyright (c) 2008-2009 Ed Schouten # All rights reserved. -# +# # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: @@ -12,7 +12,7 @@ # 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. -# +# # THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 diff --git a/sys/teken/libteken/teken.3 b/sys/teken/libteken/teken.3 index 2a9b291..1c2ebbe 100644 --- a/sys/teken/libteken/teken.3 +++ b/sys/teken/libteken/teken.3 @@ -148,7 +148,7 @@ These defaults can be modified using and .Fn teken_set_defattr . .Pp -The +The .Fn teken_get_sequence function is a utility function that can be used to obtain escape sequences of special keyboard keys, generated by user input. diff --git a/sys/teken/teken.c b/sys/teken/teken.c index cdc2cb3..8ca88d2 100644 --- a/sys/teken/teken.c +++ b/sys/teken/teken.c @@ -526,7 +526,7 @@ teken_get_sequence(teken_t *t, unsigned int k) /* Default xterm sequences. */ if (k < sizeof special_strings_normal / sizeof(char *)) return (special_strings_normal[k]); - + return (NULL); } diff --git a/sys/teken/teken_subr.h b/sys/teken/teken_subr.h index 2934bcc..f4c78f4 100644 --- a/sys/teken/teken_subr.h +++ b/sys/teken/teken_subr.h @@ -260,7 +260,7 @@ teken_subr_cursor_backward_tabulation(teken_t *t, unsigned int ntabs) break; t->t_cursor.tp_col--; - + /* Tab marker set. */ if (teken_tab_isset(t, t->t_cursor.tp_col)) ntabs--; @@ -303,7 +303,7 @@ teken_subr_cursor_forward_tabulation(teken_t *t, unsigned int ntabs) break; t->t_cursor.tp_col++; - + /* Tab marker set. */ if (teken_tab_isset(t, t->t_cursor.tp_col)) ntabs--; -- cgit v1.1 From 4ef034d1ea803fc7e2746f9360ad74f8e6ac77be Mon Sep 17 00:00:00 2001 From: ed Date: Sun, 26 Jun 2011 18:26:20 +0000 Subject: Fix whitespace inconsistencies in the TTY layer and its drivers owned by me. --- sys/dev/pty/pty.c | 6 +++--- sys/dev/snp/snp.c | 4 ++-- sys/dev/syscons/scterm-teken.c | 4 ++-- sys/kern/tty.c | 24 ++++++++++++------------ sys/kern/tty_inq.c | 8 ++++---- sys/kern/tty_outq.c | 2 +- sys/kern/tty_pts.c | 6 +++--- sys/kern/tty_ttydisc.c | 20 ++++++++++---------- 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/sys/dev/pty/pty.c b/sys/dev/pty/pty.c index 5a542cb..5e2d822 100644 --- a/sys/dev/pty/pty.c +++ b/sys/dev/pty/pty.c @@ -79,7 +79,7 @@ ptydev_fdopen(struct cdev *dev, int fflags, struct thread *td, struct file *fp) /* Raise a warning when a legacy PTY has been allocated. */ if (pty_warningcnt > 0) { pty_warningcnt--; - log(LOG_INFO, "pid %d (%s) is using legacy pty devices%s\n", + log(LOG_INFO, "pid %d (%s) is using legacy pty devices%s\n", td->td_proc->p_pid, td->td_name, pty_warningcnt ? "" : " - not logging anymore"); } @@ -139,8 +139,8 @@ static int pty_modevent(module_t mod, int type, void *data) { - switch(type) { - case MOD_LOAD: + switch(type) { + case MOD_LOAD: EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000); make_dev_credf(MAKEDEV_ETERNAL_KLD, &ptmx_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0666, "ptmx"); diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c index 37d9965..b05ad2a 100644 --- a/sys/dev/snp/snp.c +++ b/sys/dev/snp/snp.c @@ -158,7 +158,7 @@ snp_read(struct cdev *dev, struct uio *uio, int flag) error = devfs_get_cdevpriv((void **)&ss); if (error != 0) return (error); - + tp = ss->snp_tty; if (tp == NULL || tty_gone(tp)) return (EIO); @@ -198,7 +198,7 @@ snp_write(struct cdev *dev, struct uio *uio, int flag) error = devfs_get_cdevpriv((void **)&ss); if (error != 0) return (error); - + tp = ss->snp_tty; if (tp == NULL || tty_gone(tp)) return (EIO); diff --git a/sys/dev/syscons/scterm-teken.c b/sys/dev/syscons/scterm-teken.c index 1d110ab9..725f9f5 100644 --- a/sys/dev/syscons/scterm-teken.c +++ b/sys/dev/syscons/scterm-teken.c @@ -643,7 +643,7 @@ scteken_copy(void *arg, const teken_rect_t *r, const teken_pos_t *p) while (src < end) { sc_vtb_move(&scp->vtb, src, dst, width); - + src += scp->xsize; dst += scp->xsize; } @@ -658,7 +658,7 @@ scteken_copy(void *arg, const teken_rect_t *r, const teken_pos_t *p) while (src >= end) { sc_vtb_move(&scp->vtb, src, dst, width); - + src -= scp->xsize; dst -= scp->xsize; } diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 8aa3af2..f6475cb 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -470,10 +470,10 @@ ttydev_write(struct cdev *dev, struct uio *uio, int ioflag) if (error) goto done; } - - tp->t_flags |= TF_BUSY_OUT; + + tp->t_flags |= TF_BUSY_OUT; error = ttydisc_write(tp, uio, ioflag); - tp->t_flags &= ~TF_BUSY_OUT; + tp->t_flags &= ~TF_BUSY_OUT; cv_signal(&tp->t_outserwait); } @@ -1054,7 +1054,7 @@ tty_rel_pgrp(struct tty *tp, struct pgrp *pg) if (tp->t_pgrp == pg) tp->t_pgrp = NULL; - + tty_unlock(tp); } @@ -1241,7 +1241,7 @@ tty_signal_sessleader(struct tty *tp, int sig) /* Make signals start output again. */ tp->t_flags &= ~TF_STOPPED; - + if (tp->t_session != NULL && tp->t_session->s_leader != NULL) { p = tp->t_session->s_leader; PROC_LOCK(p); @@ -1305,7 +1305,7 @@ tty_wait(struct tty *tp, struct cv *cv) /* Restart the system call when we may have been revoked. */ if (tp->t_revokecnt != revokecnt) return (ERESTART); - + /* Bail out when the device slipped away. */ if (tty_gone(tp)) return (ENXIO); @@ -1327,7 +1327,7 @@ tty_timedwait(struct tty *tp, struct cv *cv, int hz) /* Restart the system call when we may have been revoked. */ if (tp->t_revokecnt != revokecnt) return (ERESTART); - + /* Bail out when the device slipped away. */ if (tty_gone(tp)) return (ENXIO); @@ -1469,7 +1469,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag, return (error); /* XXX: CLOCAL? */ - + tp->t_termios.c_cflag = t->c_cflag & ~CIGNORE; tp->t_termios.c_ispeed = t->c_ispeed; tp->t_termios.c_ospeed = t->c_ospeed; @@ -1708,7 +1708,7 @@ tty_ioctl(struct tty *tp, u_long cmd, void *data, int fflag, struct thread *td) if (tty_gone(tp)) return (ENXIO); - + error = ttydevsw_ioctl(tp, cmd, data, td); if (error == ENOIOCTL) error = tty_generic_ioctl(tp, cmd, data, fflag, td); @@ -1786,7 +1786,7 @@ ttyhook_defrint(struct tty *tp, char c, int flags) if (ttyhook_rint_bypass(tp, &c, 1) != 1) return (-1); - + return (0); } @@ -1812,7 +1812,7 @@ ttyhook_register(struct tty **rtp, struct proc *p, int fd, error = EBADF; goto done1; } - + /* * Make sure the vnode is bound to a character device. * Unlocked check for the vnode type is ok there, because we @@ -1910,7 +1910,7 @@ ttyconsdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td) /* System console has no TTY associated. */ if (dev_console->si_drv1 == NULL) return (ENXIO); - + return (ttydev_open(dev, oflags, devtype, td)); } diff --git a/sys/kern/tty_inq.c b/sys/kern/tty_inq.c index b0e9b18..0c39a29 100644 --- a/sys/kern/tty_inq.c +++ b/sys/kern/tty_inq.c @@ -142,7 +142,7 @@ void ttyinq_free(struct ttyinq *ti) { struct ttyinq_block *tib; - + ttyinq_flush(ti); ti->ti_quota = 0; @@ -276,7 +276,7 @@ ttyinq_write(struct ttyinq *ti, const void *buf, size_t nbytes, int quote) struct ttyinq_block *tib; unsigned int boff; size_t l; - + while (nbytes > 0) { boff = ti->ti_end % TTYINQ_DATASIZE; @@ -313,7 +313,7 @@ ttyinq_write(struct ttyinq *ti, const void *buf, size_t nbytes, int quote) nbytes -= l; ti->ti_end += l; } - + return (cbuf - (const char *)buf); } @@ -397,7 +397,7 @@ ttyinq_peekchar(struct ttyinq *ti, char *c, int *quote) *c = tib->tib_data[boff]; *quote = GETBIT(tib, boff); - + return (0); } diff --git a/sys/kern/tty_outq.c b/sys/kern/tty_outq.c index d5ed221..5d40abe 100644 --- a/sys/kern/tty_outq.c +++ b/sys/kern/tty_outq.c @@ -119,7 +119,7 @@ void ttyoutq_free(struct ttyoutq *to) { struct ttyoutq_block *tob; - + ttyoutq_flush(to); to->to_quota = 0; diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index d89c183..a3db59b 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -295,7 +295,7 @@ ptsdev_ioctl(struct file *fp, u_long cmd, void *data, return (EINVAL); return copyout(p, fgn->buf, i); } - + /* * We need to implement TIOCGPGRP and TIOCGSID here again. When * called on the pseudo-terminal master, it should not check if @@ -563,7 +563,7 @@ ptsdev_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, sb->st_uid = dev->si_uid; sb->st_gid = dev->si_gid; sb->st_mode = dev->si_mode | S_IFCHR; - + return (0); } @@ -823,7 +823,7 @@ posix_openpt(struct thread *td, struct posix_openpt_args *uap) */ if (uap->flags & ~(O_RDWR|O_NOCTTY)) return (EINVAL); - + error = falloc(td, &fp, &fd, 0); if (error) return (error); diff --git a/sys/kern/tty_ttydisc.c b/sys/kern/tty_ttydisc.c index 6afac8d..2a0bb4b 100644 --- a/sys/kern/tty_ttydisc.c +++ b/sys/kern/tty_ttydisc.c @@ -270,13 +270,13 @@ ttydisc_read_raw_interbyte_timer(struct tty *tp, struct uio *uio, int ioflag) MPASS(tp->t_termios.c_cc[VMIN] != 0); MPASS(tp->t_termios.c_cc[VTIME] != 0); - + /* * When using the interbyte timer, the timer should be started * after the first byte has been received. We just call into the * generic read timer code after we've received the first byte. */ - + for (;;) { error = ttyinq_read_uio(&tp->t_inq, tp, uio, uio->uio_resid, 0); @@ -331,7 +331,7 @@ ttydisc_read(struct tty *tp, struct uio *uio, int ioflag) /* Unset the input watermark when we've got enough space. */ tty_hiwat_in_unblock(tp); } - + return (error); } @@ -521,7 +521,7 @@ ttydisc_write(struct tty *tp, struct uio *uio, int ioflag) error = EWOULDBLOCK; goto done; } - + /* * The driver may write back the data * synchronously. Be sure to check the high @@ -567,7 +567,7 @@ ttydisc_optimize(struct tty *tp) } else if (!CMP_FLAG(i, ICRNL|IGNCR|IMAXBEL|INLCR|ISTRIP|IXON) && (!CMP_FLAG(i, BRKINT) || CMP_FLAG(i, IGNBRK)) && (!CMP_FLAG(i, PARMRK) || - CMP_FLAG(i, IGNPAR|IGNBRK) == (IGNPAR|IGNBRK)) && + CMP_FLAG(i, IGNPAR|IGNBRK) == (IGNPAR|IGNBRK)) && !CMP_FLAG(l, ECHO|ICANON|IEXTEN|ISIG|PENDIN)) { tp->t_flags |= TF_BYPASS; } else { @@ -583,7 +583,7 @@ ttydisc_modem(struct tty *tp, int open) if (open) cv_broadcast(&tp->t_dcdwait); - + /* * Ignore modem status lines when CLOCAL is turned on, but don't * enter the zombie state when the TTY isn't opened, because @@ -834,7 +834,7 @@ ttydisc_rint(struct tty *tp, char c, int flags) if (ttyhook_hashook(tp, rint)) return ttyhook_rint(tp, c, flags); - + if (tp->t_flags & TF_BYPASS) goto processed; @@ -1072,7 +1072,7 @@ ttydisc_rint_bypass(struct tty *tp, const void *buf, size_t len) size_t ret; tty_lock_assert(tp, MA_OWNED); - + MPASS(tp->t_flags & TF_BYPASS); atomic_add_long(&tty_nin, len); @@ -1122,7 +1122,7 @@ ttydisc_rint_poll(struct tty *tp) l = ttyinq_bytesleft(&tp->t_inq); if (l == 0 && (tp->t_flags & TF_HIWAT_IN) == 0) return (1); - + return (l); } @@ -1201,7 +1201,7 @@ ttydisc_getc_uio(struct tty *tp, struct uio *uio) tty_unlock(tp); error = uiomove(buf, len, uio); tty_lock(tp); - + if (error != 0) break; } -- cgit v1.1 From e9ebd6639ddfde813ebdd9882ef630063a45db60 Mon Sep 17 00:00:00 2001 From: ed Date: Sun, 26 Jun 2011 18:27:17 +0000 Subject: Fix whitespace inconsistencies in libc in files copyrighted by me. --- lib/libc/gen/getutxent.3 | 4 ++-- lib/libc/gen/posix_spawn.3 | 2 +- lib/libc/gen/posix_spawn.c | 4 ++-- lib/libc/gen/pututxline.c | 4 ++-- lib/libc/stdlib/ptsname.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/libc/gen/getutxent.3 b/lib/libc/gen/getutxent.3 index 5c8b793..1920555 100644 --- a/lib/libc/gen/getutxent.3 +++ b/lib/libc/gen/getutxent.3 @@ -175,7 +175,7 @@ prefix, corresponding with the device used to facilitate the user login session. If no TTY character device is used, this field is left blank. This field is only applicable to entries of type -.Dv USER_PROCESS +.Dv USER_PROCESS and .Dv LOGIN_PROCESS . .It Fa ut_host @@ -473,7 +473,7 @@ are extensions. .Sh HISTORY These functions appeared in .Fx 9.0 . -They replaced the +They replaced the .In utmp.h interface. .Sh AUTHORS diff --git a/lib/libc/gen/posix_spawn.3 b/lib/libc/gen/posix_spawn.3 index 3d902bf..73359b4 100644 --- a/lib/libc/gen/posix_spawn.3 +++ b/lib/libc/gen/posix_spawn.3 @@ -167,7 +167,7 @@ group IDs for the child process are changed as specified in the attributes object referenced by .Fa attrp . .It -The file actions specified by the spawn file actions object are +The file actions specified by the spawn file actions object are performed in the order in which they were added to the spawn file actions object. .It diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c index 58044b3..e4ceb20 100644 --- a/lib/libc/gen/posix_spawn.c +++ b/lib/libc/gen/posix_spawn.c @@ -182,7 +182,7 @@ process_file_actions(const posix_spawn_file_actions_t fa) if (error) return (error); } - return (0); + return (0); } static int @@ -193,7 +193,7 @@ do_posix_spawn(pid_t *pid, const char *path, { pid_t p; volatile int error = 0; - + p = vfork(); switch (p) { case -1: diff --git a/lib/libc/gen/pututxline.c b/lib/libc/gen/pututxline.c index 4caa00c..0cc7a01 100644 --- a/lib/libc/gen/pututxline.c +++ b/lib/libc/gen/pututxline.c @@ -57,7 +57,7 @@ futx_open(const char *file) errno = EFTYPE; return (NULL); } - + fp = fdopen(fd, "r+"); if (fp == NULL) { _close(fd); @@ -103,7 +103,7 @@ utx_active_add(const struct futx *fu) /* Allow us to overwrite unused records. */ if (partial == -1) { partial = ftello(fp); - /* + /* * Distinguish errors from valid values so we * don't overwrite good data by accident. */ diff --git a/lib/libc/stdlib/ptsname.c b/lib/libc/stdlib/ptsname.c index fc3b719..40b140d 100644 --- a/lib/libc/stdlib/ptsname.c +++ b/lib/libc/stdlib/ptsname.c @@ -82,7 +82,7 @@ ptsname(int fildes) /* Make sure fildes points to a master device. */ if (__isptmaster(fildes) != 0) goto done; - + if (fdevname_r(fildes, pt_slave + (sizeof _PATH_DEV - 1), sizeof pt_slave - (sizeof _PATH_DEV - 1)) != NULL) ret = pt_slave; -- cgit v1.1 From d2ac8b8fc00997a88c5e276ae185aa67237adfea Mon Sep 17 00:00:00 2001 From: dim Date: Sun, 26 Jun 2011 19:03:33 +0000 Subject: For some reason, contrib/traceroute/traceroute.c ensures MAXHOSTNAMELEN is defined, but then proceeds to use a hardcoded maximum hostname length of 64 anyway. Fix this by checking against MAXHOSTNAMELEN instead. PR: bin/157732 MFC after: 3 days --- contrib/traceroute/traceroute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/traceroute/traceroute.c b/contrib/traceroute/traceroute.c index 2a5fea2..1c98262 100644 --- a/contrib/traceroute/traceroute.c +++ b/contrib/traceroute/traceroute.c @@ -1618,7 +1618,7 @@ gethostinfo(register char *hostname) register char **p; register u_int32_t addr, *ap; - if (strlen(hostname) > 64) { + if (strlen(hostname) >= MAXHOSTNAMELEN) { Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n", prog, hostname); exit(1); -- cgit v1.1 From 75acd605ce922794fe235e8ef59acfdde2b2ccc4 Mon Sep 17 00:00:00 2001 From: jilles Date: Sun, 26 Jun 2011 20:12:05 +0000 Subject: sh: Include instead of non-standard . --- bin/sh/arith_yacc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/sh/arith_yacc.c b/bin/sh/arith_yacc.c index f1ac59e..041e638 100644 --- a/bin/sh/arith_yacc.c +++ b/bin/sh/arith_yacc.c @@ -35,7 +35,7 @@ #include __FBSDID("$FreeBSD$"); -#include +#include #include #include #include -- cgit v1.1 From 22d4b198f71062a8350ee0ae9c064159d33d9b33 Mon Sep 17 00:00:00 2001 From: cperciva Date: Mon, 27 Jun 2011 02:10:10 +0000 Subject: Rewrite HISTORY: The SHA256 code first appeared in 6.0, and the SHA512 code in 9.0; neither existed in FreeBSD 4.0. --- lib/libmd/sha256.3 | 2 +- lib/libmd/sha512.3 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libmd/sha256.3 b/lib/libmd/sha256.3 index fb96100..f40e6df 100644 --- a/lib/libmd/sha256.3 +++ b/lib/libmd/sha256.3 @@ -127,7 +127,7 @@ argument is non-null it must point to at least 65 characters of buffer space. .Xr sha 3 .Sh HISTORY These functions appeared in -.Fx 4.0 . +.Fx 6.0 . .Sh AUTHORS The core hash routines were implemented by Colin Percival based on the published diff --git a/lib/libmd/sha512.3 b/lib/libmd/sha512.3 index 45a4096..953ee25 100644 --- a/lib/libmd/sha512.3 +++ b/lib/libmd/sha512.3 @@ -127,7 +127,7 @@ argument is non-null it must point to at least 65 characters of buffer space. .Xr sha 3 .Sh HISTORY These functions appeared in -.Fx 4.0 . +.Fx 9.0 . .Sh AUTHORS The core hash routines were implemented by Colin Percival based on the published -- cgit v1.1 From aeac662df6e1c2cc1c8a92db283958eaa305f6a6 Mon Sep 17 00:00:00 2001 From: adrian Date: Mon, 27 Jun 2011 05:57:14 +0000 Subject: Print out a big warning if DFS can't find a channel to use. This way people debugging DFS won't be surprised when their AP stops talking. --- sys/net80211/ieee80211_dfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/net80211/ieee80211_dfs.c b/sys/net80211/ieee80211_dfs.c index e15445d..19e552d 100644 --- a/sys/net80211/ieee80211_dfs.c +++ b/sys/net80211/ieee80211_dfs.c @@ -320,6 +320,8 @@ ieee80211_dfs_notify_radar(struct ieee80211com *ic, struct ieee80211_channel *ch * on the NOL to expire. */ /*XXX*/ + if_printf(ic->ic_ifp, "%s: No free channels; waiting for entry " + "on NOL to expire\n", __func__); } } else { /* -- cgit v1.1 From 6a3c287a8944f41a733f12cb13fcab4f087b96dd Mon Sep 17 00:00:00 2001 From: pjd Date: Mon, 27 Jun 2011 09:10:48 +0000 Subject: Log a warning if we cannot sandbox using capsicum, but only under debug level 1. It would be too noisy to log it as a proper warning as CAPABILITIES are not compiled into GENERIC by default. MFC after: 3 days --- sbin/hastd/subr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sbin/hastd/subr.c b/sbin/hastd/subr.c index 806338b..4e9dee0 100644 --- a/sbin/hastd/subr.c +++ b/sbin/hastd/subr.c @@ -230,9 +230,13 @@ drop_privs(struct hast_resource *res) * ioctls and secondary uses ioctls to handle BIO_DELETE and BIO_FLUSH. * For now capsicum is only used to sandbox hastctl. */ - if (res == NULL) + if (res == NULL) { capsicum = (cap_enter() == 0); - else + if (!capsicum) { + pjdlog_common(LOG_DEBUG, 1, errno, + "Unable to sandbox using capsicum"); + } + } else capsicum = false; /* -- cgit v1.1 From faa028ceabd36900890c02260e8f7e780a235a31 Mon Sep 17 00:00:00 2001 From: pjd Date: Mon, 27 Jun 2011 09:14:25 +0000 Subject: Compile capsicum support only if HAVE_CAPSICUM is defined. MFC after: 3 days --- sbin/hastd/subr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sbin/hastd/subr.c b/sbin/hastd/subr.c index 4e9dee0..89ffda0 100644 --- a/sbin/hastd/subr.c +++ b/sbin/hastd/subr.c @@ -31,7 +31,9 @@ #include __FBSDID("$FreeBSD$"); +#ifdef HAVE_CAPSICUM #include +#endif #include #include #include @@ -230,6 +232,7 @@ drop_privs(struct hast_resource *res) * ioctls and secondary uses ioctls to handle BIO_DELETE and BIO_FLUSH. * For now capsicum is only used to sandbox hastctl. */ +#ifdef HAVE_CAPSICUM if (res == NULL) { capsicum = (cap_enter() == 0); if (!capsicum) { @@ -237,6 +240,7 @@ drop_privs(struct hast_resource *res) "Unable to sandbox using capsicum"); } } else +#endif capsicum = false; /* -- cgit v1.1 From bfdf57abb6fca38cfaa291a8949cf125eb2912f2 Mon Sep 17 00:00:00 2001 From: pjd Date: Mon, 27 Jun 2011 09:15:41 +0000 Subject: Compile hastd and hastctl with capsicum support. X-MFC after: capsicum merge --- sbin/hastctl/Makefile | 1 + sbin/hastd/Makefile | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sbin/hastctl/Makefile b/sbin/hastctl/Makefile index b7b1db9..af946a2 100644 --- a/sbin/hastctl/Makefile +++ b/sbin/hastctl/Makefile @@ -21,6 +21,7 @@ MAN= hastctl.8 NO_WFORMAT= CFLAGS+=-I${.CURDIR}/../hastd +CFLAGS+=-DHAVE_CAPSICUM CFLAGS+=-DINET .if ${MK_INET6_SUPPORT} != "no" CFLAGS+=-DINET6 diff --git a/sbin/hastd/Makefile b/sbin/hastd/Makefile index 1ffd0a2..3c4eef1 100644 --- a/sbin/hastd/Makefile +++ b/sbin/hastd/Makefile @@ -20,8 +20,9 @@ SRCS+= y.tab.h MAN= hastd.8 hast.conf.5 NO_WFORMAT= -CFLAGS+=-DPROTO_TCP_DEFAULT_PORT=8457 CFLAGS+=-I${.CURDIR} +CFLAGS+=-DHAVE_CAPSICUM +CFLAGS+=-DPROTO_TCP_DEFAULT_PORT=8457 CFLAGS+=-DINET .if ${MK_INET6_SUPPORT} != "no" CFLAGS+=-DINET6 -- cgit v1.1 From c7b111bbcf014d13ab4bcabf0d7e68e5f9a5e5b7 Mon Sep 17 00:00:00 2001 From: ae Date: Mon, 27 Jun 2011 10:42:06 +0000 Subject: MS Windows NT+ uses 4 bytes at offset 0x1b8 in the MBR to identify disk drive. The boot0cfg(8) utility preserves these 4 bytes when is writing bootcode to keep a multiboot ability. Change gpart's bootcode method to keep DSN if it is not zero. Also do not allow writing bootcode with size not equal to MBRSIZE. PR: kern/157819 Tested by: Eir Nym MFC after: 1 month --- sys/geom/part/g_part_mbr.c | 14 ++++++++------ sys/sys/diskmbr.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index 825a109..bebdfee 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -237,14 +237,16 @@ static int g_part_mbr_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp) { struct g_part_mbr_table *table; - size_t codesz; + uint32_t dsn; + + if (gpp->gpp_codesize != MBRSIZE) + return (ENODEV); - codesz = DOSPARTOFF; table = (struct g_part_mbr_table *)basetable; - bzero(table->mbr, codesz); - codesz = MIN(codesz, gpp->gpp_codesize); - if (codesz > 0) - bcopy(gpp->gpp_codeptr, table->mbr, codesz); + dsn = *(uint32_t *)(table->mbr + DOSDSNOFF); + bcopy(gpp->gpp_codeptr, table->mbr, DOSPARTOFF); + if (dsn != 0) + *(uint32_t *)(table->mbr + DOSDSNOFF) = dsn; return (0); } diff --git a/sys/sys/diskmbr.h b/sys/sys/diskmbr.h index 5aa275c..5b62e64 100644 --- a/sys/sys/diskmbr.h +++ b/sys/sys/diskmbr.h @@ -36,6 +36,7 @@ #include #define DOSBBSECTOR 0 /* DOS boot block relative sector number */ +#define DOSDSNOFF 440 /* WinNT/2K/XP Drive Serial Number offset */ #define DOSPARTOFF 446 #define DOSPARTSIZE 16 #define NDOSPART 4 -- cgit v1.1 From b39e872c065c9d08545e06a5cde1909aaac01db6 Mon Sep 17 00:00:00 2001 From: glebius Date: Mon, 27 Jun 2011 12:21:11 +0000 Subject: Add possibility to pass IPv6 packets to a divert(4) socket. Submitted by: sem --- sys/modules/ipdivert/Makefile | 7 +- sys/netinet/ip_divert.c | 157 +++++++++++++++++++++++++++--------------- sys/netinet/ipfw/ip_fw_pfil.c | 30 +++++++- 3 files changed, 136 insertions(+), 58 deletions(-) diff --git a/sys/modules/ipdivert/Makefile b/sys/modules/ipdivert/Makefile index 203b4bf..886802a 100644 --- a/sys/modules/ipdivert/Makefile +++ b/sys/modules/ipdivert/Makefile @@ -3,6 +3,11 @@ .PATH: ${.CURDIR}/../../netinet KMOD= ipdivert -SRCS= ip_divert.c +SRCS= ip_divert.c opt_inet6.h + +.if !defined(KERNBUILDDIR) +opt_inet6.h: + echo "#define INET6 1" > ${.TARGET} +.endif .include diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 527ce56..29a5d42 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #error "IPDIVERT requires INET." #endif #endif +#include "opt_inet6.h" #include #include @@ -62,6 +63,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef INET6 +#include +#include +#endif #ifdef SCTP #include #endif @@ -312,10 +317,10 @@ static int div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, struct mbuf *control) { + struct ip *const ip = mtod(m, struct ip *); struct m_tag *mtag; struct ipfw_rule_ref *dt; int error = 0; - struct mbuf *options; /* * An mbuf may hasn't come from userland, but we pretend @@ -367,71 +372,103 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, /* Reinject packet into the system as incoming or outgoing */ if (!sin || sin->sin_addr.s_addr == 0) { - struct ip *const ip = mtod(m, struct ip *); + struct mbuf *options = NULL; struct inpcb *inp; dt->info |= IPFW_IS_DIVERT | IPFW_INFO_OUT; inp = sotoinpcb(so); INP_RLOCK(inp); - /* - * Don't allow both user specified and setsockopt options, - * and don't allow packet length sizes that will crash - */ - if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) || - ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) { - error = EINVAL; - INP_RUNLOCK(inp); - m_freem(m); - } else { + switch (ip->ip_v) { + case IPVERSION: + /* + * Don't allow both user specified and setsockopt + * options, and don't allow packet length sizes that + * will crash. + */ + if ((((ip->ip_hl << 2) != sizeof(struct ip)) && + inp->inp_options != NULL) || + ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) { + error = EINVAL; + INP_RUNLOCK(inp); + goto cantsend; + } + /* Convert fields to host order for ip_output() */ ip->ip_len = ntohs(ip->ip_len); ip->ip_off = ntohs(ip->ip_off); + break; +#ifdef INET6 + case IPV6_VERSION >> 4: + { + struct ip6_hdr *const ip6 = mtod(m, struct ip6_hdr *); + + /* Don't allow packet length sizes that will crash */ + if (((u_short)ntohs(ip6->ip6_plen) > m->m_pkthdr.len)) { + error = EINVAL; + INP_RUNLOCK(inp); + goto cantsend; + } - /* Send packet to output processing */ - KMOD_IPSTAT_INC(ips_rawout); /* XXX */ + ip6->ip6_plen = ntohs(ip6->ip6_plen); + } +#endif + default: + error = EINVAL; + INP_RUNLOCK(inp); + goto cantsend; + } + + /* Send packet to output processing */ + KMOD_IPSTAT_INC(ips_rawout); /* XXX */ #ifdef MAC - mac_inpcb_create_mbuf(inp, m); + mac_inpcb_create_mbuf(inp, m); #endif - /* - * Get ready to inject the packet into ip_output(). - * Just in case socket options were specified on the - * divert socket, we duplicate them. This is done - * to avoid having to hold the PCB locks over the call - * to ip_output(), as doing this results in a number of - * lock ordering complexities. - * - * Note that we set the multicast options argument for - * ip_output() to NULL since it should be invariant that - * they are not present. - */ - KASSERT(inp->inp_moptions == NULL, - ("multicast options set on a divert socket")); - options = NULL; - /* - * XXXCSJP: It is unclear to me whether or not it makes - * sense for divert sockets to have options. However, - * for now we will duplicate them with the INP locks - * held so we can use them in ip_output() without - * requring a reference to the pcb. - */ - if (inp->inp_options != NULL) { - options = m_dup(inp->inp_options, M_DONTWAIT); - if (options == NULL) - error = ENOBUFS; - } - INP_RUNLOCK(inp); - if (error == ENOBUFS) { - m_freem(m); - return (error); + /* + * Get ready to inject the packet into ip_output(). + * Just in case socket options were specified on the + * divert socket, we duplicate them. This is done + * to avoid having to hold the PCB locks over the call + * to ip_output(), as doing this results in a number of + * lock ordering complexities. + * + * Note that we set the multicast options argument for + * ip_output() to NULL since it should be invariant that + * they are not present. + */ + KASSERT(inp->inp_moptions == NULL, + ("multicast options set on a divert socket")); + /* + * XXXCSJP: It is unclear to me whether or not it makes + * sense for divert sockets to have options. However, + * for now we will duplicate them with the INP locks + * held so we can use them in ip_output() without + * requring a reference to the pcb. + */ + if (inp->inp_options != NULL) { + options = m_dup(inp->inp_options, M_NOWAIT); + if (options == NULL) { + INP_RUNLOCK(inp); + error = ENOBUFS; + goto cantsend; } + } + INP_RUNLOCK(inp); + + switch (ip->ip_v) { + case IPVERSION: error = ip_output(m, options, NULL, - ((so->so_options & SO_DONTROUTE) ? - IP_ROUTETOIF : 0) | IP_ALLOWBROADCAST | - IP_RAWOUTPUT, NULL, NULL); - if (options != NULL) - m_freem(options); + ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) + | IP_ALLOWBROADCAST | IP_RAWOUTPUT, NULL, NULL); + break; +#ifdef INET6 + case IPV6_VERSION >> 4: + error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL); + break; +#endif } + if (options != NULL) + m_freem(options); } else { dt->info |= IPFW_IS_DIVERT | IPFW_INFO_IN; if (m->m_pkthdr.rcvif == NULL) { @@ -456,14 +493,26 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, mac_socket_create_mbuf(so, m); #endif /* Send packet to input processing via netisr */ - netisr_queue_src(NETISR_IP, (uintptr_t)so, m); + switch (ip->ip_v) { + case IPVERSION: + netisr_queue_src(NETISR_IP, (uintptr_t)so, m); + break; +#ifdef INET6 + case IPV6_VERSION >> 4: + netisr_queue_src(NETISR_IPV6, (uintptr_t)so, m); + break; +#endif + default: + error = EINVAL; + goto cantsend; + } } - return error; + return (error); cantsend: m_freem(m); - return error; + return (error); } static int diff --git a/sys/netinet/ipfw/ip_fw_pfil.c b/sys/netinet/ipfw/ip_fw_pfil.c index f076436..736615b 100644 --- a/sys/netinet/ipfw/ip_fw_pfil.c +++ b/sys/netinet/ipfw/ip_fw_pfil.c @@ -58,6 +58,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef INET6 +#include +#include +#endif #include #include @@ -265,7 +269,7 @@ ipfw_divert(struct mbuf **m0, int incoming, struct ipfw_rule_ref *rule, * If not tee, consume packet and send it to divert socket. */ struct mbuf *clone; - struct ip *ip; + struct ip *ip = mtod(*m0, struct ip *); struct m_tag *tag; /* Cloning needed for tee? */ @@ -289,8 +293,9 @@ ipfw_divert(struct mbuf **m0, int incoming, struct ipfw_rule_ref *rule, * Note that we now have the 'reass' ipfw option so if we care * we can do it before a 'tee'. */ - ip = mtod(clone, struct ip *); - if (!tee && ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)) { + if (!tee) switch (ip->ip_v) { + case IPVERSION: + if (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)) { int hlen; struct mbuf *reass; @@ -312,7 +317,26 @@ ipfw_divert(struct mbuf **m0, int incoming, struct ipfw_rule_ref *rule, else ip->ip_sum = in_cksum(reass, hlen); clone = reass; + } + break; +#ifdef INET6 + case IPV6_VERSION >> 4: + { + struct ip6_hdr *const ip6 = mtod(clone, struct ip6_hdr *); + + if (ip6->ip6_nxt == IPPROTO_FRAGMENT) { + int nxt, off; + + off = sizeof(struct ip6_hdr); + nxt = frag6_input(&clone, &off, 0); + if (nxt == IPPROTO_DONE) + return (0); + } + break; + } +#endif } + /* attach a tag to the packet with the reinject info */ tag = m_tag_alloc(MTAG_IPFW_RULE, 0, sizeof(struct ipfw_rule_ref), M_NOWAIT); -- cgit v1.1 From a85d7e899af004fb866a83d5694e8972e012126e Mon Sep 17 00:00:00 2001 From: ae Date: Mon, 27 Jun 2011 12:42:48 +0000 Subject: EBR could contain an early stage of boot code. But we do not support it. Remove message about non empty bootcode, we can not break something while GEOM_PART_EBR_COMPAT is defined. But without GEOM_PART_EBR_COMPAT any changes in EBR are allowed and we can accidentally wipe the boot code. To do not break anything save the first EBR chunk and keep it untouched each time when we are changing EBR. Note that we are still not support boot code for EBR. PR: kern/141235 MFC after: 1 month --- sys/geom/part/g_part_ebr.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/sys/geom/part/g_part_ebr.c b/sys/geom/part/g_part_ebr.c index 8ea9b47..85b8a8a 100644 --- a/sys/geom/part/g_part_ebr.c +++ b/sys/geom/part/g_part_ebr.c @@ -59,6 +59,9 @@ FEATURE(geom_part_ebr_compat, struct g_part_ebr_table { struct g_part_table base; +#ifndef GEOM_PART_EBR_COMPAT + u_char ebr[EBRSIZE]; +#endif }; struct g_part_ebr_entry { @@ -459,7 +462,7 @@ g_part_ebr_read(struct g_part_table *basetable, struct g_consumer *cp) u_char *buf; off_t ofs, msize; u_int lba; - int error, index, sum; + int error, index; pp = cp->provider; table = (struct g_part_ebr_table *)basetable; @@ -482,20 +485,11 @@ g_part_ebr_read(struct g_part_table *basetable, struct g_consumer *cp) printf("GEOM: %s: invalid entries in the EBR ignored.\n", pp->name); } - /* We do not support bootcode for EBR. If bootcode area is - * not zeroes, then mark this EBR as corrupt to do not break - * anything for another OS'es. - */ - if (lba == 0) { - sum = 0; - for (index = 0; index < DOSPARTOFF; index++) - sum += buf[index]; - if (sum != 0) { - basetable->gpt_corrupt = 1; - printf("GEOM: %s: EBR has non empty bootcode.\n", - pp->name); - } - } +#ifndef GEOM_PART_EBR_COMPAT + /* Save the first EBR, it can contain a boot code */ + if (lba == 0) + bcopy(buf, table->ebr, sizeof(table->ebr)); +#endif g_free(buf); if (ent[0].dp_typ == 0) @@ -583,6 +577,9 @@ g_part_ebr_type(struct g_part_table *basetable, struct g_part_entry *baseentry, static int g_part_ebr_write(struct g_part_table *basetable, struct g_consumer *cp) { +#ifndef GEOM_PART_EBR_COMPAT + struct g_part_ebr_table *table; +#endif struct g_provider *pp; struct g_part_entry *baseentry, *next; struct g_part_ebr_entry *entry; @@ -592,6 +589,10 @@ g_part_ebr_write(struct g_part_table *basetable, struct g_consumer *cp) pp = cp->provider; buf = g_malloc(pp->sectorsize, M_WAITOK | M_ZERO); +#ifndef GEOM_PART_EBR_COMPAT + table = (struct g_part_ebr_table *)basetable; + bcopy(table->ebr, buf, DOSPARTOFF); +#endif le16enc(buf + DOSMAGICOFFSET, DOSMAGIC); baseentry = LIST_FIRST(&basetable->gpt_entry); @@ -644,7 +645,10 @@ g_part_ebr_write(struct g_part_table *basetable, struct g_consumer *cp) error = g_write_data(cp, baseentry->gpe_start * pp->sectorsize, buf, pp->sectorsize); - +#ifndef GEOM_PART_EBR_COMPAT + if (baseentry->gpe_start == 0) + bzero(buf, DOSPARTOFF); +#endif baseentry = next; } while (!error && baseentry != NULL); -- cgit v1.1 From 0ba7056c72d2c6e7f6bb86a7196d396432068aa5 Mon Sep 17 00:00:00 2001 From: se Date: Mon, 27 Jun 2011 13:23:51 +0000 Subject: Add macros to specify owner, group and mode of config files for installation. Submitted by: Chris Rees (crees) --- share/mk/bsd.own.mk | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index a589fba..ee78619 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -63,6 +63,15 @@ # SHAREMODE ASCII text file mode. [${NOBINMODE}] # # +# CONFDIR Base path for configuration files. [/etc] +# +# CONFOWN Configuration file owner. [root] +# +# CONFGRP Configuration file group. [wheel] +# +# CONFMODE Configuration file mode. [644] +# +# # DOCDIR Base path for system documentation (e.g. PSD, USD, # handbook, FAQ etc.). [${SHAREDIR}/doc] # @@ -145,6 +154,11 @@ SHAREOWN?= root SHAREGRP?= wheel SHAREMODE?= ${NOBINMODE} +CONFDIR?= /etc +CONFOWN?= root +CONFGRP?= wheel +CONFMODE?= 644 + MANDIR?= ${SHAREDIR}/man/man MANOWN?= ${SHAREOWN} MANGRP?= ${SHAREGRP} -- cgit v1.1 From 89aadb1676787591088050bab3592e814d22ec11 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 27 Jun 2011 13:58:24 +0000 Subject: - Remove the fake BPB from zfsldr. zfsldr doesn't support booting from floppies, so it will not be used as the start of an emulated floppy image on a bootable CD which is what the fake BPB was used for. - Only check that EDD packet mode is available once at the start of zfsldr rather than for each disk sector now that we read data in one sector at a time. As a result, collapse the remaining bits of read up into nread and rename nread to read. - Restore a return at the end of putstr that I removed in the previous revision. Tested by: Henri Hennebert (earlier version) MFC after: 1 week --- sys/boot/i386/zfsboot/Makefile | 2 +- sys/boot/i386/zfsboot/zfsldr.S | 111 +++++++++++------------------------------ 2 files changed, 31 insertions(+), 82 deletions(-) diff --git a/sys/boot/i386/zfsboot/Makefile b/sys/boot/i386/zfsboot/Makefile index 65df86f..16b2e53 100644 --- a/sys/boot/i386/zfsboot/Makefile +++ b/sys/boot/i386/zfsboot/Makefile @@ -57,7 +57,7 @@ zfsboot1: zfsldr.out objcopy -S -O binary zfsldr.out ${.TARGET} zfsldr.out: zfsldr.o - ${LD} ${LDFLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} zfsldr.o + ${LD} ${LDFLAGS} -e main -Ttext ${ORG1} -o ${.TARGET} zfsldr.o CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \ zfsboot.o zfsboot.s zfsboot.s.tmp sio.o cons.o drv.o util.o diff --git a/sys/boot/i386/zfsboot/zfsldr.S b/sys/boot/i386/zfsboot/zfsldr.S index 471a042..87e04d5 100644 --- a/sys/boot/i386/zfsboot/zfsldr.S +++ b/sys/boot/i386/zfsboot/zfsldr.S @@ -34,46 +34,9 @@ .set SIZ_SEC,0x200 # Sector size .set NSECT,0x80 - .globl start + .globl main .code16 -start: jmp main # Start recognizably - -/* - * This is the start of a standard BIOS Parameter Block (BPB). Most bootable - * FAT disks have this at the start of their MBR. While normal BIOS's will - * work fine without this section, IBM's El Torito emulation "fixes" up the - * BPB by writing into the memory copy of the MBR. Rather than have data - * written into our code, we'll define a BPB to work around it. - * The data marked with (T) indicates a field required for a ThinkPad to - * recognize the disk and (W) indicates fields written from IBM BIOS code. - * The use of the BPB is based on what OpenBSD and NetBSD implemented in - * their boot code but the required fields were determined by trial and error. - * - * Note: If additional space is needed in boot1, one solution would be to - * move the "prompt" message data (below) to replace the OEM ID. - */ - .org 0x03, 0x00 -oemid: .space 0x08, 0x00 # OEM ID - - .org 0x0b, 0x00 -bpb: .word 512 # sector size (T) - .byte 0 # sectors/clustor - .word 0 # reserved sectors - .byte 0 # number of FATs - .word 0 # root entries - .word 0 # small sectors - .byte 0 # media type (W) - .word 0 # sectors/fat - .word 18 # sectors per track (T) - .word 2 # number of heads (T) - .long 0 # hidden sectors (W) - .long 0 # large sectors - - .org 0x24, 0x00 -ebpb: .byte 0 # BIOS physical drive number (W) - - .org 0x25,0x90 /* * Load the rest of zfsboot2 and BTX up, copy the parts to the right locations, * and start it all up. @@ -90,18 +53,17 @@ main: cld # String ops inc mov %cx,%ss # Set up mov $start,%sp # stack /* - * If we are on a hard drive, then load the MBR and look for the first - * FreeBSD slice. We use the fake partition entry below that points to - * the MBR when we call nread. The first pass looks for the first active - * FreeBSD slice. The second pass looks for the first non-active FreeBSD - * slice if the first one fails. + * Load the MBR and look for the first FreeBSD slice. We use the fake + * partition entry below that points to the MBR when we call read. + * The first pass looks for the first active FreeBSD slice. The + * second pass looks for the first non-active FreeBSD slice if the + * first one fails. */ + call check_edd # Make sure EDD works mov $part4,%si # Dummy partition - cmpb $0x80,%dl # Hard drive? - jb main.4 # No xor %eax,%eax # Read MBR movl $MEM_BUF,%ebx # from first - callw nread # sector + call read # sector mov $0x1,%cx # Two passes main.1: mov $MEM_BUF+PRT_OFF,%si # Partition table movb $0x1,%dh # Partition @@ -122,10 +84,6 @@ main.3: add $0x10,%si # Next entry */ mov $msg_part,%si # Message jmp error # Error -/* - * Floppies use partition 0 of drive 0. - */ -main.4: xor %dx,%dx # Partition:drive /* * Ok, we have a slice and drive in %dx now, so use that to locate and @@ -153,7 +111,7 @@ main.5: mov %dx,MEM_ARG # Save args movl $1024,%eax # Offset to boot2 mov $MEM_BTX,%ebx # Destination buffer main.6: pushal # Save params - callw nread # Read disk + call read # Read disk popal # Restore incl %eax # Advance to add $SIZ_SEC,%ebx # next sector @@ -200,16 +158,16 @@ seta20.3: sti # Enable interrupts /* - * Trampoline used to call read from within zfsldr. Sets up an EDD - * packet on the stack and passes it to read. We assume that the - * destination address is always segment-aligned. + * Read a sector from the disk. Sets up an EDD packet on the stack + * and passes it to read. We assume that the destination address is + * always segment-aligned. * * %eax - int - LBA to read in relative to partition start * %ebx - ptr - destination address * %dl - byte - drive to read from * %si - ptr - MBR partition entry */ -nread: xor %ecx,%ecx # Get +read: xor %ecx,%ecx # Get addl 0x8(%si),%eax # LBA adc $0,%ecx pushl %ecx # Starting absolute block @@ -219,12 +177,13 @@ nread: xor %ecx,%ecx # Get push $0 # transfer buffer push $0x1 # Read 1 sector push $0x10 # Size of packet - mov %sp,%bp # Packet pointer - callw read # Read from disk - jc nread.1 # If error, fail - lea 0x10(%bp),%sp # Clear stack + mov %sp,%si # Packet pointer + mov $0x42,%ah # BIOS: Extended + int $0x13 # read + jc read.1 # If error, fail + lea 0x10(%si),%sp # Clear stack ret # If success, return -nread.1: mov %ah,%al # Format +read.1: mov %ah,%al # Format mov $read_err,%di # error call hex8 # code mov $msg_read,%si # Set the error message and @@ -250,36 +209,26 @@ putstr.0: mov $0x7,%bx # Page:attribute putstr: lodsb # Get char testb %al,%al # End of string? jne putstr.0 # No - + ret # To caller /* - * Reads sectors from the disk. If EDD is enabled, then check if it is - * installed and use it if it is. If it is not installed or not enabled, then - * fall back to using CHS. Since we use a LBA, if we are using CHS, we have to - * fetch the drive parameters from the BIOS and divide it out ourselves. - * Call with: - * - * %dl - byte - drive number - * stack - 10 bytes - EDD Packet + * Check to see if the disk supports EDD. zfsboot requires EDD and does not + * support older C/H/S disk I/O. */ -read: cmpb $0x80,%dl # Hard drive? - jb read.1 # No, use CHS +check_edd: cmpb $0x80,%dl # Hard drive? + jb check_edd.1 # No, fail to boot mov $0x55aa,%bx # Magic push %dx # Save movb $0x41,%ah # BIOS: Check int $0x13 # extensions present pop %dx # Restore - jc read.1 # If error, use CHS + jc check_edd.1 # If error, fail cmp $0xaa55,%bx # Magic? - jne read.1 # No, so use CHS + jne check_edd.1 # No, so fail testb $0x1,%cl # Packet interface? - jz read.1 # No, so use CHS - mov %bp,%si # Disk packet - movb $0x42,%ah # BIOS: Extended - int $0x13 # read - retw # To caller -read.1: mov $msg_chs,%si - jmp error - + jz check_edd.1 # No, so fail + ret # EDD ok, keep booting +check_edd.1: mov $msg_chs,%si # Warn that CHS is + jmp error # unsupported and fail /* * AL to hex, saving the result to [EDI]. */ -- cgit v1.1 From bef398d46374b8ecb38e350dbdb621d94c7a641e Mon Sep 17 00:00:00 2001 From: nwhitehorn Date: Mon, 27 Jun 2011 16:24:36 +0000 Subject: Build Scrt.o on powerpc64. Its introduction on other platforms got lost during the period of time the powerpc64 port was on a project branch. --- lib/csu/powerpc64/Makefile | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/csu/powerpc64/Makefile b/lib/csu/powerpc64/Makefile index 04926ad..095a9ad 100644 --- a/lib/csu/powerpc64/Makefile +++ b/lib/csu/powerpc64/Makefile @@ -4,15 +4,14 @@ SRCS= crt1.c crti.S crtn.S OBJS= ${SRCS:N*.h:R:S/$/.o/g} -OBJS+= gcrt1.o -CFLAGS+= -Wall -Wno-unused \ - -I${.CURDIR}/../common \ +OBJS+= Scrt1.o gcrt1.o +CFLAGS+= -I${.CURDIR}/../common \ -I${.CURDIR}/../../libc/include all: ${OBJS} CLEANFILES= ${OBJS} -CLEANFILES+= crt1.s gcrt1.s +CLEANFILES+= crt1.s gcrt1.s Scrt1.s # See the comment in lib/csu/common/crtbrand.c for the reason crt1.c is not # directly compiled to .o files. @@ -31,6 +30,13 @@ gcrt1.s: crt1.c gcrt1.o: gcrt1.s ${CC} ${CFLAGS} -c -o ${.TARGET} gcrt1.s +Scrt1.s: crt1.c + ${CC} ${CFLAGS} -fPIC -DPIC -S -o ${.TARGET} ${.CURDIR}/crt1.c + sed -i "" -e '/\.note\.ABI-tag/s/progbits/note/' ${.TARGET} + +Scrt1.o: Scrt1.s + ${CC} ${CFLAGS} -c -o ${.TARGET} Scrt1.s + realinstall: ${INSTALL} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ ${OBJS} ${DESTDIR}${LIBDIR} -- cgit v1.1 From b6ff66c80a3c0b78754d094966acc7366b1512d4 Mon Sep 17 00:00:00 2001 From: hselasky Date: Mon, 27 Jun 2011 20:32:19 +0000 Subject: Regenerate usb.conf after r223566. --- etc/devd/usb.conf | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/etc/devd/usb.conf b/etc/devd/usb.conf index 5dbbd0a..568be15 100644 --- a/etc/devd/usb.conf +++ b/etc/devd/usb.conf @@ -1533,15 +1533,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x083a"; - match "product" "0x4506"; - action "kldload if_uath"; -}; - -nomatch 32 { - match "bus" "uhub[0-9]+"; - match "mode" "host"; - match "vendor" "0x083a"; - match "product" "0x4506"; + match "product" "(0x4505|0x4506)"; action "kldload if_zyd"; }; -- cgit v1.1 From c6509394cf48a6061ce794b4379bf941770e5762 Mon Sep 17 00:00:00 2001 From: yongari Date: Mon, 27 Jun 2011 21:27:12 +0000 Subject: Disable microcode loading for 82550 and 82550C controllers. Loading the microcode caused SCB timeouts. Linux driver does not allow microcode loading for these controllers and jfv also confirmed that there is no need to do and it shouldn't. PR: kern/103332 Additional confirmation from: jfv MFC after: 1 week --- sys/dev/fxp/if_fxp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index e02d580..ea94821 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -3012,8 +3012,10 @@ static uint32_t fxp_ucode_d101a[] = D101_A_RCVBUNDLE_UCODE; static uint32_t fxp_ucode_d101b0[] = D101_B0_RCVBUNDLE_UCODE; static uint32_t fxp_ucode_d101ma[] = D101M_B_RCVBUNDLE_UCODE; static uint32_t fxp_ucode_d101s[] = D101S_RCVBUNDLE_UCODE; +#ifdef notyet static uint32_t fxp_ucode_d102[] = D102_B_RCVBUNDLE_UCODE; static uint32_t fxp_ucode_d102c[] = D102_C_RCVBUNDLE_UCODE; +#endif static uint32_t fxp_ucode_d102e[] = D102_E_RCVBUNDLE_UCODE; #define UCODE(x) x, sizeof(x)/sizeof(uint32_t) @@ -3031,10 +3033,12 @@ static const struct ucode { D101M_CPUSAVER_DWORD, D101M_CPUSAVER_BUNDLE_MAX_DWORD }, { FXP_REV_82559S_A, UCODE(fxp_ucode_d101s), D101S_CPUSAVER_DWORD, D101S_CPUSAVER_BUNDLE_MAX_DWORD }, +#ifdef notyet { FXP_REV_82550, UCODE(fxp_ucode_d102), D102_B_CPUSAVER_DWORD, D102_B_CPUSAVER_BUNDLE_MAX_DWORD }, { FXP_REV_82550_C, UCODE(fxp_ucode_d102c), D102_C_CPUSAVER_DWORD, D102_C_CPUSAVER_BUNDLE_MAX_DWORD }, +#endif { FXP_REV_82551_F, UCODE(fxp_ucode_d102e), D102_E_CPUSAVER_DWORD, D102_E_CPUSAVER_BUNDLE_MAX_DWORD }, { 0, NULL, 0, 0, 0 } -- cgit v1.1 From 67d464a1d85e037a433554e5ec4bc141cd2fd967 Mon Sep 17 00:00:00 2001 From: yongari Date: Mon, 27 Jun 2011 21:37:38 +0000 Subject: Enable CPUSaver D102 E-step microcode loading for 82551 revision 0x10. --- sys/dev/fxp/if_fxp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index ea94821..62c8dc2 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -3041,6 +3041,8 @@ static const struct ucode { #endif { FXP_REV_82551_F, UCODE(fxp_ucode_d102e), D102_E_CPUSAVER_DWORD, D102_E_CPUSAVER_BUNDLE_MAX_DWORD }, + { FXP_REV_82551_10, UCODE(fxp_ucode_d102e), + D102_E_CPUSAVER_DWORD, D102_E_CPUSAVER_BUNDLE_MAX_DWORD }, { 0, NULL, 0, 0, 0 } }; -- cgit v1.1 From 86a602b0bf1853f59794afbf6a837090b0090257 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 27 Jun 2011 21:43:56 +0000 Subject: Revert the entry point label to 'start' to unbreak the build. Pointy hat to: jhb --- sys/boot/i386/zfsboot/Makefile | 2 +- sys/boot/i386/zfsboot/zfsldr.S | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/boot/i386/zfsboot/Makefile b/sys/boot/i386/zfsboot/Makefile index 16b2e53..65df86f 100644 --- a/sys/boot/i386/zfsboot/Makefile +++ b/sys/boot/i386/zfsboot/Makefile @@ -57,7 +57,7 @@ zfsboot1: zfsldr.out objcopy -S -O binary zfsldr.out ${.TARGET} zfsldr.out: zfsldr.o - ${LD} ${LDFLAGS} -e main -Ttext ${ORG1} -o ${.TARGET} zfsldr.o + ${LD} ${LDFLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} zfsldr.o CLEANFILES+= zfsboot2 zfsboot.ld zfsboot.ldr zfsboot.bin zfsboot.out \ zfsboot.o zfsboot.s zfsboot.s.tmp sio.o cons.o drv.o util.o diff --git a/sys/boot/i386/zfsboot/zfsldr.S b/sys/boot/i386/zfsboot/zfsldr.S index 87e04d5..b8be282 100644 --- a/sys/boot/i386/zfsboot/zfsldr.S +++ b/sys/boot/i386/zfsboot/zfsldr.S @@ -34,7 +34,7 @@ .set SIZ_SEC,0x200 # Sector size .set NSECT,0x80 - .globl main + .globl start .code16 /* @@ -46,7 +46,7 @@ * Setup the segment registers to flat addressing (segment 0) and setup the * stack to end just below the start of our code. */ -main: cld # String ops inc +start: cld # String ops inc xor %cx,%cx # Zero mov %cx,%es # Address mov %cx,%ds # data -- cgit v1.1 From 0d864997ca182472eae6ca74ba9ff37ef79453c7 Mon Sep 17 00:00:00 2001 From: tuexen Date: Mon, 27 Jun 2011 22:03:33 +0000 Subject: Add support for SCTP_PR_SCTP_NONE which I misded to add. This constant is defined in the socket API ID. MFC after: 2 months. --- sys/netinet/sctp_uio.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index a798682..d3b186d 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -251,12 +251,13 @@ struct sctp_snd_all_completes { /* for the endpoint */ /* The lower byte is an enumeration of PR-SCTP policies */ +#define SCTP_PR_SCTP_NONE 0x0000/* Reliable transfer */ #define SCTP_PR_SCTP_TTL 0x0001/* Time based PR-SCTP */ #define SCTP_PR_SCTP_BUF 0x0002/* Buffer based PR-SCTP */ #define SCTP_PR_SCTP_RTX 0x0003/* Number of retransmissions based PR-SCTP */ #define PR_SCTP_POLICY(x) ((x) & 0x0f) -#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != 0) +#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE) #define PR_SCTP_TTL_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL) #define PR_SCTP_BUF_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF) #define PR_SCTP_RTX_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX) -- cgit v1.1 From 612e8bfe92f4c6a722f8acef3c978f054264d0a7 Mon Sep 17 00:00:00 2001 From: adrian Date: Tue, 28 Jun 2011 00:01:55 +0000 Subject: Make sure the extended regdomain word is initialised. As with the AR9285, the AR9287 has a default word of 0x1F which means all the various bits in that field are set on by default. --- sys/dev/ath/ath_hal/ah_eeprom_9287.h | 2 ++ sys/dev/ath/ath_hal/ar9002/ar9287_attach.c | 1 + 2 files changed, 3 insertions(+) diff --git a/sys/dev/ath/ath_hal/ah_eeprom_9287.h b/sys/dev/ath/ath_hal/ah_eeprom_9287.h index d429c39..ff8080a 100644 --- a/sys/dev/ath/ath_hal/ah_eeprom_9287.h +++ b/sys/dev/ath/ath_hal/ah_eeprom_9287.h @@ -31,6 +31,8 @@ #define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER #define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1 +#define AR9287_RDEXT_DEFAULT 0x1F + #define AR9287_EEP_START_LOC 128 #define AR9287_HTC_EEP_START_LOC 256 #define AR9287_NUM_2G_CAL_PIERS 3 diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c index f3b403b..ed9feb8 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c @@ -320,6 +320,7 @@ ar9287Attach(uint16_t devid, HAL_SOFTC sc, /* Read Reg Domain */ AH_PRIVATE(ah)->ah_currentRD = ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL); + AH_PRIVATE(ah)->ah_currentRDext = AR9287_RDEXT_DEFAULT; /* * ah_miscMode is populated by ar5416FillCapabilityInfo() -- cgit v1.1 From 009e9866663d9661d3a075015e162cad604b684c Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 28 Jun 2011 00:58:12 +0000 Subject: Incorporate vendor commit ecdc5c0a7f7591a7cd4a: In userland, sign extend the offset for JA instructions. We currently use that to implement "ip6 protochain", and "pc" might be wider than "pc->k", in which case we need to arrange that "pc->k" be sign-extended, by casting it to bpf_int32. PR: kern/157188 Submitted by: plosher MFC after: 2 weeks --- contrib/libpcap/bpf/net/bpf_filter.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/contrib/libpcap/bpf/net/bpf_filter.c b/contrib/libpcap/bpf/net/bpf_filter.c index db12bb2..f172384 100644 --- a/contrib/libpcap/bpf/net/bpf_filter.c +++ b/contrib/libpcap/bpf/net/bpf_filter.c @@ -405,7 +405,18 @@ bpf_filter(pc, p, wirelen, buflen) continue; case BPF_JMP|BPF_JA: +#if defined(KERNEL) || defined(_KERNEL) + /* + * No backward jumps allowed. + */ pc += pc->k; +#else + /* + * XXX - we currently implement "ip6 protochain" + * with backward jumps, so sign-extend pc->k. + */ + pc += (bpf_int32)pc->k; +#endif continue; case BPF_JMP|BPF_JGT|BPF_K: -- cgit v1.1 From ff36ddb644d4c0177451a08b8f042ed7ccabd196 Mon Sep 17 00:00:00 2001 From: mm Date: Tue, 28 Jun 2011 06:16:33 +0000 Subject: Allow mountpoints as arguments for the 'zfs get' command. Illumos-gate revision: 13295 Obtained from: Illumos (Feature #510) MFC after: 1 week --- cddl/contrib/opensolaris/cmd/zfs/zfs_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c index 8383dbc..bc5a662 100644 --- a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c +++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2010 Nexenta Systems, Inc. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ #include @@ -1292,7 +1292,7 @@ static int zfs_do_get(int argc, char **argv) { zprop_get_cbdata_t cb = { 0 }; - int i, c, flags = 0; + int i, c, flags = ZFS_ITER_ARGS_CAN_BE_PATHS; char *value, *fields; int ret; int limit = 0; -- cgit v1.1 From 953bf4fcbd8cfe9a78938869f7f1178e80ac1da5 Mon Sep 17 00:00:00 2001 From: mm Date: Tue, 28 Jun 2011 06:32:35 +0000 Subject: Disable vdev cache (readahead) by default. The vdev cache is very underutilized (hit ratio 30%-70%) and may consume excessive memory on systems with many vdevs. Illumos-gate revision: 13346 Obtained from: Illumos (Bug #175) MFC after: 1 week --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c index 7978d61..ef9d4b5 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c @@ -71,9 +71,16 @@ * 1< Date: Tue, 28 Jun 2011 07:52:01 +0000 Subject: Add a new "REFCOMPRESSRATIO" property. For snapshots, this is the same as COMPRESSRATIO, but for filesystems/volumes, the COMPRESSRATIO is based on the data "USED" (ie, includes blocks in children, but not blocks shared with the origin). This is needed to figure out how much space a filesystem would use if it were not compressed (ignoring snapshots). Illumos-gate revision: 13387 Obtained from: Illumos (Feature #1092) MFC after: 2 weeks --- cddl/contrib/opensolaris/cmd/zfs/zfs.8 | 16 ++++++++++++++-- .../opensolaris/lib/libzfs/common/libzfs_dataset.c | 2 ++ sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c | 4 ++++ .../contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c | 13 ++++++++----- sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h | 2 ++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 index 0d40a90..e5d8590 100644 --- a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 +++ b/cddl/contrib/opensolaris/cmd/zfs/zfs.8 @@ -6,6 +6,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. .\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with .\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] +.\" Copyright 2011 by Delphix. All rights reserved. .TH zfs 1M "24 Sep 2009" "SunOS 5.11" "System Administration Commands" .SH NAME zfs \- configures ZFS file systems @@ -389,7 +390,7 @@ This property can also be referred to by its shortened column name, \fBavail\fR. .ad .sp .6 .RS 4n -The compression ratio achieved for this dataset, expressed as a multiplier. Compression can be turned on by running: \fBzfs set compression=on \fIdataset\fR\fR. The default value is \fBoff\fR. +For non-snapshots, the compression ratio achieved for the \fBused\fR space of this dataset, expressed as a multiplier. The \fBused\fR property includes descendant datasets, and, for clones, does not include the space shared with the origin snapshot. For snapshots, the \fBcompressratio\fR is the same as the \fBrefcompressratio\fR property. Compression can be turned on by running: \fBzfs set compression=on \fIdataset\fR\fR. The default value is \fBoff\fR. .RE .sp @@ -453,6 +454,17 @@ This property can also be referred to by its shortened column name, \fBrefer\fR. .ne 2 .mk .na +\fB\fBrefcompressratio\fR\fR +.ad +.sp .6 +.RS 4n +The compression ratio achieved for the \fBreferenced\fR space of this dataset, expressed as a multiplier. See also the \fBcompressratio\fR property. +.RE + +.sp +.ne 2 +.mk +.na \fB\fBtype\fR\fR .ad .sp .6 @@ -1278,7 +1290,7 @@ Recursively destroy all dependents, including cloned file systems outside the ta Force an unmount of any file systems using the \fBunmount -f\fR command. This option has no effect on non-file systems or unmounted file systems. .RE -Extreme care should be taken when applying either the \fB-r\fR or the \fB-f\fR options, as they can destroy large portions of a pool and cause unexpected behavior for mounted file systems in use. +Extreme care should be taken when applying either the \fB-r\fR or the \fB-R\fR options, as they can destroy large portions of a pool and cause unexpected behavior for mounted file systems in use. .RE .sp diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c index 824834e..82f4925 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2010 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ #include @@ -2038,6 +2039,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, } break; + case ZFS_PROP_REFRATIO: case ZFS_PROP_COMPRESSRATIO: if (get_numeric_property(zhp, prop, src, &source, &val) != 0) return (-1); diff --git a/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c b/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c index 434b482..4fa75195 100644 --- a/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c +++ b/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -311,6 +312,9 @@ zfs_prop_init(void) zprop_register_number(ZFS_PROP_COMPRESSRATIO, "compressratio", 0, PROP_READONLY, ZFS_TYPE_DATASET, "<1.00x or higher if compressed>", "RATIO"); + zprop_register_number(ZFS_PROP_REFRATIO, "refcompressratio", 0, + PROP_READONLY, ZFS_TYPE_DATASET, + "<1.00x or higher if compressed>", "REFRATIO"); zprop_register_number(ZFS_PROP_VOLBLOCKSIZE, "volblocksize", ZVOL_DEFAULT_BLOCKSIZE, PROP_ONETIME, ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK"); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c index 7170aba..498352e 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ #include @@ -2150,7 +2151,7 @@ dsl_dataset_sync(dsl_dataset_t *ds, zio_t *zio, dmu_tx_t *tx) void dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) { - uint64_t refd, avail, uobjs, aobjs; + uint64_t refd, avail, uobjs, aobjs, ratio; dsl_dir_stats(ds->ds_dir, nv); @@ -2177,6 +2178,11 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY, DS_IS_DEFER_DESTROY(ds) ? 1 : 0); + ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 : + (ds->ds_phys->ds_uncompressed_bytes * 100 / + ds->ds_phys->ds_compressed_bytes); + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio); + if (ds->ds_phys->ds_next_snap_obj) { /* * This is a snapshot; override the dd's space used with @@ -2184,10 +2190,7 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv) */ dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED, ds->ds_phys->ds_unique_bytes); - dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, - ds->ds_phys->ds_compressed_bytes == 0 ? 100 : - (ds->ds_phys->ds_uncompressed_bytes * 100 / - ds->ds_phys->ds_compressed_bytes)); + dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio); } } diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h index edc26cd..e4070c2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011 by Delphix. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -124,6 +125,7 @@ typedef enum { ZFS_PROP_DEDUP, ZFS_PROP_MLSLABEL, ZFS_PROP_SYNC, + ZFS_PROP_REFRATIO, ZFS_NUM_PROPS } zfs_prop_t; -- cgit v1.1 From 6e85d84e2d4c2ca228618e0e2ca34f0423690b4d Mon Sep 17 00:00:00 2001 From: kevlo Date: Tue, 28 Jun 2011 08:36:48 +0000 Subject: Remove duplicate header includes --- sys/dev/acpica/acpi_thermal.c | 1 - sys/dev/an/if_an.c | 1 - sys/dev/dc/dcphy.c | 1 - sys/dev/dc/pnphy.c | 1 - sys/dev/en/if_en_pci.c | 3 --- sys/dev/et/if_et.c | 1 - sys/dev/fdc/fdc_pccard.c | 2 -- sys/dev/iicbus/if_ic.c | 3 --- sys/dev/mfi/mfi_cam.c | 3 --- sys/dev/my/if_my.c | 1 - sys/dev/sis/if_sis.c | 1 - sys/dev/tdfx/tdfx_pci.c | 1 - sys/dev/usb/usb_msctest.c | 1 - 13 files changed, 20 deletions(-) diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c index 7226b6c..18996bd 100644 --- a/sys/dev/acpica/acpi_thermal.c +++ b/sys/dev/acpica/acpi_thermal.c @@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c index 645fe41..0898961 100644 --- a/sys/dev/an/if_an.c +++ b/sys/dev/an/if_an.c @@ -102,7 +102,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/dev/dc/dcphy.c b/sys/dev/dc/dcphy.c index f4fc512..5c60ad5 100644 --- a/sys/dev/dc/dcphy.c +++ b/sys/dev/dc/dcphy.c @@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include diff --git a/sys/dev/dc/pnphy.c b/sys/dev/dc/pnphy.c index 6468fbf..6546acd 100644 --- a/sys/dev/dc/pnphy.c +++ b/sys/dev/dc/pnphy.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include diff --git a/sys/dev/en/if_en_pci.c b/sys/dev/en/if_en_pci.c index 09ba8bc..3886c9e 100644 --- a/sys/dev/en/if_en_pci.c +++ b/sys/dev/en/if_en_pci.c @@ -44,9 +44,6 @@ __FBSDID("$FreeBSD$"); * thanks to Matt Thomas for figuring out FreeBSD vs NetBSD vs etc.. diffs. */ -#include -__FBSDID("$FreeBSD$"); - #include #include #include diff --git a/sys/dev/et/if_et.c b/sys/dev/et/if_et.c index 82c6217..9bd68e8 100644 --- a/sys/dev/et/if_et.c +++ b/sys/dev/et/if_et.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include diff --git a/sys/dev/fdc/fdc_pccard.c b/sys/dev/fdc/fdc_pccard.c index 72a3568..d959060 100644 --- a/sys/dev/fdc/fdc_pccard.c +++ b/sys/dev/fdc/fdc_pccard.c @@ -38,8 +38,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #include #include #include "pccarddevs.h" diff --git a/sys/dev/iicbus/if_ic.c b/sys/dev/iicbus/if_ic.c index 4a05b16..6ac6401 100644 --- a/sys/dev/iicbus/if_ic.c +++ b/sys/dev/iicbus/if_ic.c @@ -49,9 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include #include #include #include diff --git a/sys/dev/mfi/mfi_cam.c b/sys/dev/mfi/mfi_cam.c index 5137c36..747b6c0 100644 --- a/sys/dev/mfi/mfi_cam.c +++ b/sys/dev/mfi/mfi_cam.c @@ -54,12 +54,9 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include #include #include -#include #include #include diff --git a/sys/dev/my/if_my.c b/sys/dev/my/if_my.c index 951473a..4b59c48 100644 --- a/sys/dev/my/if_my.c +++ b/sys/dev/my/if_my.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include diff --git a/sys/dev/sis/if_sis.c b/sys/dev/sis/if_sis.c index 63417a0..9290ff7 100644 --- a/sys/dev/sis/if_sis.c +++ b/sys/dev/sis/if_sis.c @@ -87,7 +87,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/dev/tdfx/tdfx_pci.c b/sys/dev/tdfx/tdfx_pci.c index 770c672..27308a9 100644 --- a/sys/dev/tdfx/tdfx_pci.c +++ b/sys/dev/tdfx/tdfx_pci.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c index 45bd363..0b6024b 100644 --- a/sys/dev/usb/usb_msctest.c +++ b/sys/dev/usb/usb_msctest.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include #include -- cgit v1.1 From 29ff2b4aff0cd24ac5e6e02ed95642fdf23c433d Mon Sep 17 00:00:00 2001 From: pluknet Date: Tue, 28 Jun 2011 08:41:44 +0000 Subject: Update ifc_len field of struct ifconf passed for the ioctl SIOCGIFCONF32 (i.e. under COMPAT_FREEBSD32) in case ifconf() returned success to match the native SIOCGIFCONF behavior. PR: kern/158369 Reported by: Paul Procacci MFC after: 1 week --- sys/net/if.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/net/if.c b/sys/net/if.c index b7c2ad1..a5a3a8e 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2467,6 +2467,8 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td) error = ifconf(SIOCGIFCONF, (void *)&ifc); CURVNET_RESTORE(); + if (error == 0) + ifc32->ifc_len = ifc.ifc_len; return (error); } #endif -- cgit v1.1 From 5eb4e348c846241663feac5cdfc0c79ebb1e312f Mon Sep 17 00:00:00 2001 From: bz Date: Tue, 28 Jun 2011 09:46:25 +0000 Subject: Compare port numbers correctly. They are stored by SRCPORT() in host byte order, so we need to compare them as such. Properly compare IPv6 addresses as well. This allows the, by default, 8 badaddrs slots per address family to work correctly and only print sendto() errors once. The change is no longer applicable to any latest upstream versions. Approved by: roberto Sponsored by: Sandvine Incorporated MFC after: 1 week --- contrib/ntp/ntpd/ntp_io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c index 8dac3c4..2d5572a 100644 --- a/contrib/ntp/ntpd/ntp_io.c +++ b/contrib/ntp/ntpd/ntp_io.c @@ -2716,14 +2716,14 @@ sendpkt( for (slot = ERRORCACHESIZE; --slot >= 0; ) if(dest->ss_family == AF_INET) { - if (badaddrs[slot].port == ((struct sockaddr_in*)dest)->sin_port && + if (badaddrs[slot].port == SRCPORT(dest) && badaddrs[slot].addr.s_addr == ((struct sockaddr_in*)dest)->sin_addr.s_addr) break; } #ifdef INCLUDE_IPV6_SUPPORT else if (dest->ss_family == AF_INET6) { - if (badaddrs6[slot].port == ((struct sockaddr_in6*)dest)->sin6_port && - badaddrs6[slot].addr.s6_addr == ((struct sockaddr_in6*)dest)->sin6_addr.s6_addr) + if (badaddrs6[slot].port == SRCPORT(dest) && + !memcmp(&badaddrs6[slot].addr, &((struct sockaddr_in6*)dest)->sin6_addr, sizeof(struct in6_addr))) break; } #endif /* INCLUDE_IPV6_SUPPORT */ -- cgit v1.1 From 3292a832c82ce13a810384ac0b1cace2d79ad17f Mon Sep 17 00:00:00 2001 From: edwin Date: Tue, 28 Jun 2011 10:24:01 +0000 Subject: MFV of tzdata2011h, r223627 - Russia scraps DST in 2011 - Remove Netherlands Antilles, add Bonaire, Curacao, Sint Maarten --- contrib/tzdata/antarctica | 14 +-------- contrib/tzdata/asia | 6 +++- contrib/tzdata/europe | 70 ++++++++++++++++++++++++++++++++++----------- contrib/tzdata/southamerica | 10 ++++++- contrib/tzdata/zone.tab | 6 ++-- 5 files changed, 72 insertions(+), 34 deletions(-) diff --git a/contrib/tzdata/antarctica b/contrib/tzdata/antarctica index 629b2d7..d19fbde 100644 --- a/contrib/tzdata/antarctica +++ b/contrib/tzdata/antarctica @@ -1,5 +1,5 @@ #
-# @(#)antarctica	8.8
+# @(#)antarctica	8.9
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -19,18 +19,6 @@
 # I made up all time zone abbreviations mentioned here; corrections welcome!
 # FORMAT is `zzz' and GMTOFF is 0 for locations while uninhabited.
 
-# These rules are stolen from the `europe' file.
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	RussAQ	1981	1984	-	Apr	 1	 0:00	1:00	S
-Rule	RussAQ	1981	1983	-	Oct	 1	 0:00	0	-
-Rule	RussAQ	1984	1991	-	Sep	lastSun	 2:00s	0	-
-Rule	RussAQ	1985	1991	-	Mar	lastSun	 2:00s	1:00	S
-Rule	RussAQ	1992	only	-	Mar	lastSat	 23:00	1:00	S
-Rule	RussAQ	1992	only	-	Sep	lastSat	 23:00	0	-
-Rule	RussAQ	1993	max	-	Mar	lastSun	 2:00s	1:00	S
-Rule	RussAQ	1993	1995	-	Sep	lastSun	 2:00s	0	-
-Rule	RussAQ	1996	max	-	Oct	lastSun	 2:00s	0	-
-
 # These rules are stolen from the `southamerica' file.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	ArgAQ	1964	1966	-	Mar	 1	0:00	0	-
diff --git a/contrib/tzdata/asia b/contrib/tzdata/asia
index d415ba8..1fc61f0 100644
--- a/contrib/tzdata/asia
+++ b/contrib/tzdata/asia
@@ -1,4 +1,4 @@
-# @(#)asia	8.64
+# @(#)asia	8.65
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -77,6 +77,10 @@ Rule RussiaAsia	1993	max	-	Mar	lastSun	 2:00s	1:00	S
 Rule RussiaAsia	1993	1995	-	Sep	lastSun	 2:00s	0	-
 Rule RussiaAsia	1996	max	-	Oct	lastSun	 2:00s	0	-
 
+# From Arthur David Olson (2011-06-15):
+# While Russia abandoned DST in 2011, Armenia may choose to
+# follow Russia's "old" rules.
+
 # Afghanistan
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Kabul	4:36:48 -	LMT	1890
diff --git a/contrib/tzdata/europe b/contrib/tzdata/europe
index f7fc189..aab6833 100644
--- a/contrib/tzdata/europe
+++ b/contrib/tzdata/europe
@@ -1,5 +1,5 @@
 # 
-# @(#)europe	8.32
+# @(#)europe	8.33
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -565,6 +565,26 @@ Rule	Russia	1993	max	-	Mar	lastSun	 2:00s	1:00	S
 Rule	Russia	1993	1995	-	Sep	lastSun	 2:00s	0	-
 Rule	Russia	1996	max	-	Oct	lastSun	 2:00s	0	-
 
+# From Alexander Krivenyshev (2011-06-14):
+# According to Kremlin press service, Russian President Dmitry Medvedev
+# signed a federal law "On calculation of time" on June 9, 2011.
+# According to the law Russia is abolishing daylight saving time.
+# 
+# Medvedev signed a law "On the Calculation of Time" (in russian): 
+# 
+# http://bmockbe.ru/events/?ID=7583
+# 
+# 
+# Medvedev signed a law on the calculation of the time (in russian):
+# 
+# http://www.regnum.ru/news/polit/1413906.html
+# 
+
+# From Arthur David Olson (2011-06-15):
+# Take "abolishing daylight saving time" to mean that time is now considered
+# to be standard.
+# At least for now, keep the "old" Russia rules for the benefit of Belarus.
+
 # These are for backward compatibility with older versions.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2013,7 +2033,8 @@ Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
 			 1:00	C-Eur	CE%sT	1945
 			 2:00	Poland	CE%sT	1946
 			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT
+			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
+			 3:00	-	EET
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
 # Respublika Adygeya, Arkhangel'skaya oblast',
@@ -2042,7 +2063,8 @@ Zone Europe/Moscow	 2:30:20 -	LMT	1880
 			 2:00	-	EET	1930 Jun 21
 			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
 			 2:00	Russia	EE%sT	1992 Jan 19 2:00s
-			 3:00	Russia	MSK/MSD
+			 3:00	Russia	MSK/MSD	2011 Mar 27 2:00s
+			 4:00	-	MSK
 #
 # Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
 # Volgogradskaya oblast'.  Shanks & Pottenger say Kirov is still at +0400
@@ -2055,7 +2077,8 @@ Zone Europe/Volgograd	 2:57:40 -	LMT	1920 Jan  3
 			 4:00	Russia	VOL%sT	1989 Mar 26 2:00s # Volgograd T
 			 3:00	Russia	VOL%sT	1991 Mar 31 2:00s
 			 4:00	-	VOLT	1992 Mar 29 2:00s
-			 3:00	Russia	VOL%sT
+			 3:00	Russia	VOL%sT	2011 Mar 27 2:00s
+			 4:00	-	VOLT
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
 # Samarskaya oblast', Udmyrtskaya respublika
@@ -2067,7 +2090,8 @@ Zone Europe/Samara	 3:20:36 -	LMT	1919 Jul  1 2:00
 			 2:00	Russia	KUY%sT	1991 Sep 29 2:00s
 			 3:00	-	KUYT	1991 Oct 20 3:00
 			 4:00	Russia	SAM%sT	2010 Mar 28 2:00s # Samara Time
-			 3:00	Russia	SAM%sT
+			 3:00	Russia	SAM%sT	2011 Mar 27 2:00s
+			 4:00	-	SAMT
 
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
@@ -2080,7 +2104,8 @@ Zone Asia/Yekaterinburg	 4:02:24 -	LMT	1919 Jul 15 4:00
 			 4:00	-	SVET	1930 Jun 21 # Sverdlovsk Time
 			 5:00	Russia	SVE%sT	1991 Mar 31 2:00s
 			 4:00	Russia	SVE%sT	1992 Jan 19 2:00s
-			 5:00	Russia	YEK%sT	# Yekaterinburg Time
+			 5:00	Russia	YEK%sT	2011 Mar 27 2:00s
+			 6:00	-	YEKT	# Yekaterinburg Time
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
 # Respublika Altaj, Altajskij kraj, Omskaya oblast'.
@@ -2088,7 +2113,8 @@ Zone Asia/Omsk		 4:53:36 -	LMT	1919 Nov 14
 			 5:00	-	OMST	1930 Jun 21 # Omsk TIme
 			 6:00	Russia	OMS%sT	1991 Mar 31 2:00s
 			 5:00	Russia	OMS%sT	1992 Jan 19 2:00s
-			 6:00	Russia	OMS%sT
+			 6:00	Russia	OMS%sT	2011 Mar 27 2:00s
+			 7:00	-	OMST
 #
 # From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
 # not clear when it switched from +7 to +6.
@@ -2098,7 +2124,8 @@ Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
 			 7:00	Russia	NOV%sT	1991 Mar 31 2:00s
 			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
 			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
-			 6:00	Russia	NOV%sT
+			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
+			 7:00	-	NOVT
 
 # From Alexander Krivenyshev (2009-10-13):
 # Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
@@ -2131,7 +2158,8 @@ Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
 			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
 			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
 			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
-			 6:00	Russia	NOV%sT # Novosibirsk/Novokuznetsk Time
+			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
+			 7:00	-	NOVT # Novosibirsk/Novokuznetsk Time
 
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
@@ -2142,7 +2170,8 @@ Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
 			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
 			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT
+			 7:00	Russia	KRA%sT	2011 Mar 27 2:00s
+			 8:00	-	KRAT
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
 # Respublika Buryatiya, Irkutskaya oblast',
@@ -2152,7 +2181,8 @@ Zone Asia/Irkutsk	 6:57:20 -	LMT	1880
 			 7:00	-	IRKT	1930 Jun 21 # Irkutsk Time
 			 8:00	Russia	IRK%sT	1991 Mar 31 2:00s
 			 7:00	Russia	IRK%sT	1992 Jan 19 2:00s
-			 8:00	Russia	IRK%sT
+			 8:00	Russia	IRK%sT	2011 Mar 27 2:00s
+			 9:00	-	IRKT
 #
 # From Oscar van Vlijmen (2003-10-18): [This region consists of]
 # Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
@@ -2175,7 +2205,8 @@ Zone Asia/Yakutsk	 8:38:40 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
 			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
 			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
-			 9:00	Russia	YAK%sT
+			 9:00	Russia	YAK%sT	2011 Mar 27 2:00s
+			 10:00	-	YAKT
 #
 # From Oscar van Vlijmen (2003-10-18): [This region consists of]
 # Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
@@ -2188,7 +2219,8 @@ Zone Asia/Vladivostok	 8:47:44 -	LMT	1922 Nov 15
 			 9:00	-	VLAT	1930 Jun 21 # Vladivostok Time
 			10:00	Russia	VLA%sT	1991 Mar 31 2:00s
 			 9:00	Russia	VLA%sST	1992 Jan 19 2:00s
-			10:00	Russia	VLA%sT
+			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
+			11:00	-	VLAT
 #
 # Sakhalinskaya oblast'.
 # The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
@@ -2198,7 +2230,8 @@ Zone Asia/Sakhalin	 9:30:48 -	LMT	1905 Aug 23
 			11:00	Russia	SAK%sT	1991 Mar 31 2:00s # Sakhalin T.
 			10:00	Russia	SAK%sT	1992 Jan 19 2:00s
 			11:00	Russia	SAK%sT	1997 Mar lastSun 2:00s
-			10:00	Russia	SAK%sT
+			10:00	Russia	SAK%sT	2011 Mar 27 2:00s
+			11:00	-	SAKT
 #
 # From Oscar van Vlijmen (2003-10-18): [This region consists of]
 # Magadanskaya oblast', Respublika Sakha (Yakutiya).
@@ -2211,7 +2244,8 @@ Zone Asia/Magadan	10:03:12 -	LMT	1924 May  2
 			10:00	-	MAGT	1930 Jun 21 # Magadan Time
 			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
 			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT
+			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
+			12:00	-	MAGT
 #
 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
 # Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
@@ -2222,7 +2256,8 @@ Zone Asia/Kamchatka	10:34:36 -	LMT	1922 Nov 10
 			12:00	Russia	PET%sT	1991 Mar 31 2:00s
 			11:00	Russia	PET%sT	1992 Jan 19 2:00s
 			12:00	Russia	PET%sT	2010 Mar 28 2:00s
-			11:00	Russia	PET%sT
+			11:00	Russia	PET%sT	2011 Mar 27 2:00s
+			12:00	-	PETT
 #
 # Chukotskij avtonomnyj okrug
 Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
@@ -2231,7 +2266,8 @@ Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
 			12:00	Russia	ANA%sT	1991 Mar 31 2:00s
 			11:00	Russia	ANA%sT	1992 Jan 19 2:00s
 			12:00	Russia	ANA%sT	2010 Mar 28 2:00s
-			11:00	Russia	ANA%sT
+			11:00	Russia	ANA%sT	2011 Mar 27 2:00s
+			12:00	-	ANAT
 
 # Serbia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
diff --git a/contrib/tzdata/southamerica b/contrib/tzdata/southamerica
index 919dc25..90f531d 100644
--- a/contrib/tzdata/southamerica
+++ b/contrib/tzdata/southamerica
@@ -1,5 +1,5 @@
 # 
-# @(#)southamerica	8.49
+# @(#)southamerica	8.50
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -1276,6 +1276,14 @@ Zone	America/Curacao	-4:35:44 -	LMT	1912 Feb 12	# Willemstad
 			-4:30	-	ANT	1965 # Netherlands Antilles Time
 			-4:00	-	AST
 
+# From Arthur David Olson (2011-06-15):
+# At least for now, use links for places with new iso3166 codes.
+# The name "Lower Prince's Quarter" is both longer than fourteen charaters
+# and contains an apostrophe; use "Lower_Princes" below.
+
+Link	America/Curacao	America/Lower_Princes # Sint Maarten
+Link	America/Curacao	America/Kralendijk # Bonaire, Sint Estatius and Saba
+
 # Ecuador
 #
 # From Paul Eggert (2007-03-04):
diff --git a/contrib/tzdata/zone.tab b/contrib/tzdata/zone.tab
index f4afae6..2517764 100644
--- a/contrib/tzdata/zone.tab
+++ b/contrib/tzdata/zone.tab
@@ -1,5 +1,5 @@
 # 
-# @(#)zone.tab	8.43
+# @(#)zone.tab	8.45
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
@@ -32,7 +32,6 @@ AG	+1703-06148	America/Antigua
 AI	+1812-06304	America/Anguilla
 AL	+4120+01950	Europe/Tirane
 AM	+4011+04430	Asia/Yerevan
-AN	+1211-06900	America/Curacao
 AO	-0848+01314	Africa/Luanda
 AQ	-7750+16636	Antarctica/McMurdo	McMurdo Station, Ross Island
 AQ	-9000+00000	Antarctica/South_Pole	Amundsen-Scott Station, South Pole
@@ -87,6 +86,7 @@ BL	+1753-06251	America/St_Barthelemy
 BM	+3217-06446	Atlantic/Bermuda
 BN	+0456+11455	Asia/Brunei
 BO	-1630-06809	America/La_Paz
+BQ	+120903-0681636	America/Kralendijk
 BR	-0351-03225	America/Noronha	Atlantic islands
 BR	-0127-04829	America/Belem	Amapa, E Para
 BR	-0343-03830	America/Fortaleza	NE Brazil (MA, PI, CE, RN, PB)
@@ -155,6 +155,7 @@ CO	+0436-07405	America/Bogota
 CR	+0956-08405	America/Costa_Rica
 CU	+2308-08222	America/Havana
 CV	+1455-02331	Atlantic/Cape_Verde
+CW	+1211-06900	America/Curacao
 CX	-1025+10543	Indian/Christmas
 CY	+3510+03322	Asia/Nicosia
 CZ	+5005+01426	Europe/Prague
@@ -362,6 +363,7 @@ SO	+0204+04522	Africa/Mogadishu
 SR	+0550-05510	America/Paramaribo
 ST	+0020+00644	Africa/Sao_Tome
 SV	+1342-08912	America/El_Salvador
+SX	+180305-0630250	America/Lower_Princes
 SY	+3330+03618	Asia/Damascus
 SZ	-2618+03106	Africa/Mbabane
 TC	+2128-07108	America/Grand_Turk
-- 
cgit v1.1


From a963cb97121e4c58292b7deaf2a9d08d4455b21b Mon Sep 17 00:00:00 2001
From: edwin 
Date: Tue, 28 Jun 2011 10:38:12 +0000
Subject: Remove AN again now that tzdata2011h has been imported.

---
 share/misc/iso3166 | 1 -
 1 file changed, 1 deletion(-)

diff --git a/share/misc/iso3166 b/share/misc/iso3166
index d8d5972..23c9bd6 100644
--- a/share/misc/iso3166
+++ b/share/misc/iso3166
@@ -176,7 +176,6 @@ NA	NAM	516	Namibia
 NR	NRU	520	Nauru
 NP	NPL	524	Nepal
 NL	NLD	528	Netherlands
-AN	ANT	530	Netherlands Antilles
 NC	NCL	540	New Caledonia
 NZ	NZL	554	New Zealand
 NI	NIC	558	Nicaragua
-- 
cgit v1.1


From e15f804c7b67f7cac4a68d0f6b6d0418e9f7309a Mon Sep 17 00:00:00 2001
From: bz 
Date: Tue, 28 Jun 2011 11:57:25 +0000
Subject: Update packet filter (pf) code to OpenBSD 4.5.

You need to update userland (world and ports) tools
to be in sync with the kernel.

Submitted by:	mlaier
Submitted by:	eri
---
 UPDATING                              |    4 +
 contrib/pf/authpf/authpf.8            |  108 +-
 contrib/pf/authpf/authpf.c            |  376 ++-
 contrib/pf/authpf/pathnames.h         |    3 +-
 contrib/pf/ftp-proxy/filter.c         |   18 +-
 contrib/pf/ftp-proxy/filter.h         |    4 +-
 contrib/pf/ftp-proxy/ftp-proxy.8      |   29 +-
 contrib/pf/ftp-proxy/ftp-proxy.c      |  139 +-
 contrib/pf/man/pf.4                   |   22 +-
 contrib/pf/man/pf.conf.5              |  178 +-
 contrib/pf/man/pf.os.5                |    8 +-
 contrib/pf/man/pflog.4                |   10 +-
 contrib/pf/man/pfsync.4               |  141 +-
 contrib/pf/pfctl/parse.y              | 1574 ++++++---
 contrib/pf/pfctl/pf_print_state.c     |  150 +-
 contrib/pf/pfctl/pfctl.8              |  135 +-
 contrib/pf/pfctl/pfctl.c              |  231 +-
 contrib/pf/pfctl/pfctl.h              |   13 +-
 contrib/pf/pfctl/pfctl_altq.c         |   25 +-
 contrib/pf/pfctl/pfctl_optimize.c     |   15 +-
 contrib/pf/pfctl/pfctl_osfp.c         |    2 +-
 contrib/pf/pfctl/pfctl_parser.c       |   41 +-
 contrib/pf/pfctl/pfctl_parser.h       |   12 +-
 contrib/pf/pfctl/pfctl_qstats.c       |   14 +-
 contrib/pf/pfctl/pfctl_radix.c        |   52 +-
 contrib/pf/pfctl/pfctl_table.c        |   15 +-
 contrib/pf/pflogd/pflogd.8            |   22 +-
 contrib/pf/pflogd/pflogd.c            |  134 +-
 contrib/pf/pflogd/privsep.c           |    8 +-
 contrib/pf/pflogd/privsep_fdpass.c    |   20 +-
 sbin/pflogd/Makefile                  |    2 +-
 sys/conf/files                        |    4 +-
 sys/contrib/altq/altq/altq_red.c      |   11 +-
 sys/contrib/pf/net/if_pflog.c         |   47 +-
 sys/contrib/pf/net/if_pflog.h         |   26 +-
 sys/contrib/pf/net/if_pflow.h         |  126 +
 sys/contrib/pf/net/if_pfsync.c        | 4023 ++++++++++++++--------
 sys/contrib/pf/net/if_pfsync.h        |  493 ++-
 sys/contrib/pf/net/pf.c               | 5970 ++++++++++++++++-----------------
 sys/contrib/pf/net/pf_if.c            |  309 +-
 sys/contrib/pf/net/pf_ioctl.c         | 1394 +++++---
 sys/contrib/pf/net/pf_lb.c            |  792 +++++
 sys/contrib/pf/net/pf_mtag.h          |    6 +-
 sys/contrib/pf/net/pf_norm.c          |  411 ++-
 sys/contrib/pf/net/pf_osfp.c          |  140 +-
 sys/contrib/pf/net/pf_ruleset.c       |   94 +-
 sys/contrib/pf/net/pf_subr.c          |  168 -
 sys/contrib/pf/net/pf_table.c         |  430 ++-
 sys/contrib/pf/net/pfvar.h            |  798 +++--
 sys/modules/Makefile                  |    4 +
 sys/modules/pf/Makefile               |   16 +-
 sys/modules/pflog/Makefile            |   18 +-
 sys/modules/pfsync/Makefile           |   38 +
 sys/netinet/in_gif.c                  |    2 +
 sys/netinet/ip_icmp.c                 |    2 +
 sys/netinet/ipfw/ip_fw2.c             |    4 -
 sys/netinet/raw_ip.c                  |    3 +
 sys/netinet6/icmp6.c                  |    4 +
 sys/netinet6/in6_gif.c                |    2 +
 sys/netipsec/ipsec_input.c            |    2 +
 sys/netipsec/ipsec_output.c           |    2 +
 sys/netipsec/xform_ipip.c             |    2 +
 sys/sys/mbuf.h                        |   10 +
 sys/sys/param.h                       |    2 +-
 usr.sbin/ftp-proxy/ftp-proxy/Makefile |    8 +-
 65 files changed, 11568 insertions(+), 7298 deletions(-)
 create mode 100644 sys/contrib/pf/net/if_pflow.h
 create mode 100644 sys/contrib/pf/net/pf_lb.c
 delete mode 100644 sys/contrib/pf/net/pf_subr.c
 create mode 100644 sys/modules/pfsync/Makefile

diff --git a/UPDATING b/UPDATING
index be548b5..985e04e 100644
--- a/UPDATING
+++ b/UPDATING
@@ -22,6 +22,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
 	machines to maximize performance.  (To disable malloc debugging, run
 	ln -s aj /etc/malloc.conf.)
 
+20110628:
+	The packet filter (pf) code has been updated to OpenBSD 4.5.
+	You need to update userland tools to be in sync with kernel.
+
 20110608:
 	The following sysctls and tunables are retired on x86 platforms:
 		machdep.hlt_cpus
diff --git a/contrib/pf/authpf/authpf.8 b/contrib/pf/authpf/authpf.8
index bd4ff40..d365057 100644
--- a/contrib/pf/authpf/authpf.8
+++ b/contrib/pf/authpf/authpf.8
@@ -1,5 +1,5 @@
 .\" $FreeBSD$
-.\" $OpenBSD: authpf.8,v 1.43 2007/02/24 17:21:04 beck Exp $
+.\" $OpenBSD: authpf.8,v 1.47 2009/01/06 03:11:50 mcbride Exp $
 .\"
 .\" Copyright (c) 1998-2007 Bob Beck (beck@openbsd.org>.  All rights reserved.
 .\"
@@ -15,14 +15,16 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd March 28, 2006
+.Dd January 6 2009
 .Dt AUTHPF 8
 .Os
 .Sh NAME
-.Nm authpf
+.Nm authpf ,
+.Nm authpf-noip
 .Nd authenticating gateway user shell
 .Sh SYNOPSIS
 .Nm authpf
+.Nm authpf-noip
 .Sh DESCRIPTION
 .Nm
 is a user shell for authenticating gateways.
@@ -31,47 +33,63 @@ It is used to change
 rules when a user authenticates and starts a session with
 .Xr sshd 8
 and to undo these changes when the user's session exits.
-It is designed for changing filter and translation rules for an individual
-source IP address as long as a user maintains an active
-.Xr ssh 1
-session.
 Typical use would be for a gateway that authenticates users before
 allowing them Internet use, or a gateway that allows different users into
 different places.
+Combined with properly set up filter rules and secure switches,
 .Nm
-logs the successful start and end of a session to
-.Xr syslogd 8 .
-This, combined with properly set up filter rules and secure switches,
 can be used to ensure users are held accountable for their network traffic.
+It is meant to be used with users who can connect via
+.Xr ssh 1
+only, and requires the
+.Xr pf 4
+subsystem to be enabled.
 .Pp
+.Nm authpf-noip
+is a user shell
+which allows multiple connections to take
+place from the same IP address.
+It is useful primarily in cases where connections are tunneled via
+the gateway system, and can be directly associated with the user name.
+It cannot ensure accountability when
+classifying connections by IP address;
+in this case the client's IP address
+is not provided to the packet filter via the
+.Ar client_ip
+macro or the
+.Ar authpf_users
+table.
+Additionally, states associated with the client IP address
+are not purged when the session is ended.
+.Pp
+To use either
 .Nm
-can add filter and translation rules using the syntax described in
-.Xr pf.conf 5 .
-.Nm
-requires that the
-.Xr pf 4
-system be enabled and a 
-.Xr fdescfs 5
-file system be mounted at
-.Pa /dev/fd
-before use.
-.Nm
-can also maintain the list of IP address of connected users
-in the "authpf_users"
-.Pa table .
+or
+.Nm authpf-noip ,
+the user's shell needs to be set to
+.Pa /usr/sbin/authpf
+or
+.Pa /usr/sbin/authpf-noip .
 .Pp
 .Nm
-is meant to be used with users who can connect via
+uses the
+.Xr pf.conf 5
+syntax to change filter and translation rules for an individual
+user or client IP address as long as a user maintains an active
 .Xr ssh 1
-only.
-On startup,
+session, and logs the successful start and end of a session to
+.Xr syslogd 8 .
 .Nm
 retrieves the client's connecting IP address via the
 .Ev SSH_CLIENT
 environment variable and, after performing additional access checks,
 reads a template file to determine what filter and translation rules
-(if any) to add.
-On session exit the same rules that were added at startup are removed.
+(if any) to add, and
+maintains the list of IP addresses of connected users in the
+.Ar authpf_users
+table.
+On session exit the same rules and table entries that were added at startup
+are removed, and all states associated with the client's IP address are purged.
 .Pp
 Each
 .Nm
@@ -185,6 +203,9 @@ It is also possible to configure
 to only allow specific users access.
 This is done by listing their login names, one per line, in
 .Pa /etc/authpf/authpf.allow .
+A group of users can also be indicated by prepending "%" to the group name,
+and all members of a login class can be indicated by prepending "@" to the
+login class name.
 If "*" is found on a line, then all usernames match.
 If
 .Nm
@@ -297,7 +318,8 @@ They have a
 wireless network which they would like to protect from unauthorized use.
 To accomplish this, they create the file
 .Pa /etc/authpf/authpf.allow
-which lists their login ids, one per line.
+which lists their login ids, group prepended with "%", or login class
+prepended with "@", one per line.
 At this point, even if eve could authenticate to
 .Xr sshd 8 ,
 she would not be allowed to use the gateway.
@@ -501,6 +523,31 @@ table  persist
 anchor "authpf/*" from 
 rdr-anchor "authpf/*" from 
 .Ed
+.Pp
+.Sy Tunneled users
+\- normally
+.Nm
+allows only one session per client IP address.
+However in some cases, such as when connections are tunneled via
+.Xr ssh 1
+or
+.Xr ipsec 4 ,
+the connections can be authorized based on the userid of the user instead of
+the client IP address.
+In this case it is appropriate to use
+.Nm authpf-noip
+to allow multiple users behind a NAT gateway to connect.
+In the
+.Pa /etc/authpf/authpf.rules
+example below, the remote user could tunnel a remote desktop session to their
+workstation:
+.Bd -literal
+internal_if="bge0"
+workstation_ip="10.2.3.4"
+
+pass out on $internal_if from (self) to $workstation_ip port 3389 \e
+       user $user_id
+.Ed
 .Sh FILES
 .Bl -tag -width "/etc/authpf/authpf.conf" -compact
 .It Pa /etc/authpf/authpf.conf
@@ -512,7 +559,6 @@ rdr-anchor "authpf/*" from 
 .Sh SEE ALSO
 .Xr pf 4 ,
 .Xr pf.conf 5 ,
-.Xr fdescfs 5 ,
 .Xr securelevel 7 ,
 .Xr ftp-proxy 8
 .Sh HISTORY
diff --git a/contrib/pf/authpf/authpf.c b/contrib/pf/authpf/authpf.c
index 56d7728..ac5d85b 100644
--- a/contrib/pf/authpf/authpf.c
+++ b/contrib/pf/authpf/authpf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: authpf.c,v 1.104 2007/02/24 17:35:08 beck Exp $	*/
+/*	$OpenBSD: authpf.c,v 1.112 2009/01/10 19:08:53 miod Exp $	*/
 
 /*
  * Copyright (C) 1998 - 2007 Bob Beck (beck@openbsd.org).
@@ -19,7 +19,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
 #endif
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -48,10 +49,11 @@ __FBSDID("$FreeBSD$");
 #include "pathnames.h"
 
 static int	read_config(FILE *);
-static void	print_message(char *);
-static int	allowed_luser(char *);
-static int	check_luser(char *, char *);
+static void	print_message(const char *);
+static int	allowed_luser(struct passwd *);
+static int	check_luser(const char *, char *);
 static int	remove_stale_rulesets(void);
+static int	recursive_ruleset_purge(char *, char *);
 static int	change_filter(int, const char *, const char *);
 static int	change_table(int, const char *);
 static void	authpf_kill_states(void);
@@ -60,8 +62,10 @@ int	dev;			/* pf device */
 char	anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
 char	rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
 char	tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
+int	user_ip = 1;	/* controls whether $user_ip is set */
 
 FILE	*pidfp;
+int	pidfd = -1;
 char	 luser[MAXLOGNAME];	/* username */
 char	 ipsrc[256];		/* ip as a string */
 char	 pidfile[MAXPATHLEN];	/* we save pid in this file. */
@@ -75,6 +79,7 @@ static __dead2 void	do_death(int);
 #else
 static __dead void	do_death(int);
 #endif
+extern char *__progname;	/* program name */
 
 /*
  * User shell for authenticating gateways. Sole purpose is to allow
@@ -83,21 +88,24 @@ static __dead void	do_death(int);
  * up. Meant to be used only from ssh(1) connections.
  */
 int
-main(int argc, char *argv[])
+main(void)
 {
-	int		 lockcnt = 0, n, pidfd;
+	int		 lockcnt = 0, n;
 	FILE		*config;
 	struct in6_addr	 ina;
 	struct passwd	*pw;
 	char		*cp;
 	gid_t		 gid;
 	uid_t		 uid;
-	char		*shell;
+	const char	*shell;
 	login_cap_t	*lc;
 
+	if (strcmp(__progname, "-authpf-noip") == 0)
+                user_ip = 0;
+
 	config = fopen(PATH_CONFFILE, "r");
 	if (config == NULL) {
-		syslog(LOG_ERR, "can not open %s (%m)", PATH_CONFFILE);
+		syslog(LOG_ERR, "cannot open %s (%m)", PATH_CONFFILE);
 		exit(1);
 	}
 
@@ -142,23 +150,34 @@ main(int argc, char *argv[])
 	}
 
 	if ((lc = login_getclass(pw->pw_class)) != NULL)
-		shell = (char *)login_getcapstr(lc, "shell", pw->pw_shell,
+		shell = login_getcapstr(lc, "shell", pw->pw_shell,
 		    pw->pw_shell);
 	else
 		shell = pw->pw_shell;
 
+#ifndef __FreeBSD__
 	login_close(lc);
+#endif
 
-	if (strcmp(shell, PATH_AUTHPF_SHELL)) {
+	if (strcmp(shell, PATH_AUTHPF_SHELL) && 
+	    strcmp(shell, PATH_AUTHPF_SHELL_NOIP)) {
 		syslog(LOG_ERR, "wrong shell for user %s, uid %u",
 		    pw->pw_name, pw->pw_uid);
+#ifdef __FreeBSD__
+	login_close(lc);
+#else
 		if (shell != pw->pw_shell)
 			free(shell);
+#endif
 		goto die;
 	}
 
+#ifdef __FreeBSD__
+	login_close(lc);
+#else
 	if (shell != pw->pw_shell)
 		free(shell);
+#endif
 
 	/*
 	 * Paranoia, but this data _does_ come from outside authpf, and
@@ -181,13 +200,22 @@ main(int argc, char *argv[])
 	}
 
 
-	/* Make our entry in /var/authpf as /var/authpf/ipaddr */
-	n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc);
+	/* Make our entry in /var/authpf as ipaddr or username */
+	n = snprintf(pidfile, sizeof(pidfile), "%s/%s",
+	    PATH_PIDFILE, user_ip ? ipsrc : luser);
 	if (n < 0 || (u_int)n >= sizeof(pidfile)) {
 		syslog(LOG_ERR, "path to pidfile too long");
 		goto die;
 	}
 
+	signal(SIGTERM, need_death);
+	signal(SIGINT, need_death);
+	signal(SIGALRM, need_death);
+	signal(SIGPIPE, need_death);
+	signal(SIGHUP, need_death);
+	signal(SIGQUIT, need_death);
+	signal(SIGTSTP, need_death);
+
 	/*
 	 * If someone else is already using this ip, then this person
 	 * wants to switch users - so kill the old process and exit
@@ -241,15 +269,17 @@ main(int argc, char *argv[])
 		}
 
 		/*
-		 * we try to kill the previous process and acquire the lock
+		 * We try to kill the previous process and acquire the lock
 		 * for 10 seconds, trying once a second. if we can't after
-		 * 10 attempts we log an error and give up
+		 * 10 attempts we log an error and give up.
 		 */
-		if (++lockcnt > 10) {
-			syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
-			    otherpid);
+		if (want_death || ++lockcnt > 10) {
+			if (!want_death)
+				syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
+				    otherpid);
 			fclose(pidfp);
 			pidfp = NULL;
+			pidfd = -1;
 			goto dogdeath;
 		}
 		sleep(1);
@@ -260,6 +290,7 @@ main(int argc, char *argv[])
 		 */
 		fclose(pidfp);
 		pidfp = NULL;
+		pidfd = -1;
 	} while (1);
 	
 	/* whack the group list */
@@ -277,7 +308,7 @@ main(int argc, char *argv[])
 	}
 	openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
 
-	if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
+	if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(pw)) {
 		syslog(LOG_INFO, "user %s prohibited", luser);
 		do_death(0);
 	}
@@ -302,19 +333,12 @@ main(int argc, char *argv[])
 		printf("Unable to modify filters\r\n");
 		do_death(0);
 	}
-	if (change_table(1, ipsrc) == -1) {
+	if (user_ip && change_table(1, ipsrc) == -1) {
 		printf("Unable to modify table\r\n");
 		change_filter(0, luser, ipsrc);
 		do_death(0);
 	}
 
-	signal(SIGTERM, need_death);
-	signal(SIGINT, need_death);
-	signal(SIGALRM, need_death);
-	signal(SIGPIPE, need_death);
-	signal(SIGHUP, need_death);
-	signal(SIGQUIT, need_death);
-	signal(SIGTSTP, need_death);
 	while (1) {
 		printf("\r\nHello %s. ", luser);
 		printf("You are authenticated from host \"%s\"\r\n", ipsrc);
@@ -337,8 +361,6 @@ dogdeath:
 	sleep(180); /* them lusers read reaaaaal slow */
 die:
 	do_death(0);
-
-	/* NOTREACHED */
 }
 
 /*
@@ -361,6 +383,8 @@ read_config(FILE *f)
 		}
 		i++;
 		len = strlen(buf);
+		if (len == 0)
+			continue;
 		if (buf[len - 1] != '\n' && !feof(f)) {
 			syslog(LOG_ERR, "line %d too long in %s", i,
 			    PATH_CONFFILE);
@@ -413,7 +437,7 @@ parse_error:
  * they've been bad or we're unavailable.
  */
 static void
-print_message(char *filename)
+print_message(const char *filename)
 {
 	char	 buf[1024];
 	FILE	*f;
@@ -436,6 +460,7 @@ print_message(char *filename)
  * allowed_luser checks to see if user "luser" is allowed to
  * use this gateway by virtue of being listed in an allowed
  * users file, namely /etc/authpf/authpf.allow .
+ * Users may be listed by , %, or @.
  *
  * If /etc/authpf/authpf.allow does not exist, then we assume that
  * all users who are allowed in by sshd(8) are permitted to
@@ -444,9 +469,9 @@ print_message(char *filename)
  * the session terminates in the same manner as being banned.
  */
 static int
-allowed_luser(char *luser)
+allowed_luser(struct passwd *pw)
 {
-	char	*buf, *lbuf;
+	char *buf,*lbuf;
 	int	 matched;
 	size_t	 len;
 	FILE	*f;
@@ -476,8 +501,14 @@ allowed_luser(char *luser)
 		 * "public" gateway, such as it is, so let
 		 * everyone use it.
 		 */
+		int gl_init = 0, ngroups = NGROUPS + 1;
+		gid_t groups[NGROUPS + 1];
+
 		lbuf = NULL;
+		matched = 0;
+
 		while ((buf = fgetln(f, &len))) {
+			
 			if (buf[len - 1] == '\n')
 				buf[len - 1] = '\0';
 			else {
@@ -488,7 +519,40 @@ allowed_luser(char *luser)
 				buf = lbuf;
 			}
 
-			matched = strcmp(luser, buf) == 0 || strcmp("*", buf) == 0;
+			if (buf[0] == '@') {
+				/* check login class */
+				if (strcmp(pw->pw_class, buf + 1) == 0)
+					matched++;
+			} else if (buf[0] == '%') {
+				/* check group membership */
+				int cnt; 
+				struct group *group;
+
+				if ((group = getgrnam(buf + 1)) == NULL) {
+					syslog(LOG_ERR,
+					    "invalid group '%s' in %s (%s)",
+					    buf + 1, PATH_ALLOWFILE,
+				 	    strerror(errno));
+					return (0);
+				}
+
+				if (!gl_init) {
+					(void) getgrouplist(pw->pw_name,
+					    pw->pw_gid, groups, &ngroups);
+					gl_init++;
+				}
+			
+				for ( cnt = 0; cnt < ngroups; cnt++) {
+					if (group->gr_gid == groups[cnt]) {
+						matched++;
+						break;
+					}
+				}
+			} else {
+				/* check username and wildcard */
+				matched = strcmp(pw->pw_name, buf) == 0 ||
+				    strcmp("*", buf) == 0;
+			}
 
 			if (lbuf != NULL) {
 				free(lbuf);
@@ -496,13 +560,13 @@ allowed_luser(char *luser)
 			}
 
 			if (matched)
-				return (1); /* matched an allowed username */
+				return (1); /* matched an allowed user/group */
 		}
 		syslog(LOG_INFO, "denied access to %s: not listed in %s",
-		    luser, PATH_ALLOWFILE);
+		    pw->pw_name, PATH_ALLOWFILE);
 
 		/* reuse buf */
-		buf = "\n\nSorry, you are not allowed to use this facility!\n";
+		sprintf(buf, "%s", "\n\nSorry, you are not allowed to use this facility!\n");
 		fputs(buf, stdout);
 	}
 	fflush(stdout);
@@ -520,13 +584,13 @@ allowed_luser(char *luser)
  * going to be un-banned.)
  */
 static int
-check_luser(char *luserdir, char *luser)
+check_luser(const char *luserdir, char *l_user)
 {
 	FILE	*f;
 	int	 n;
 	char	 tmp[MAXPATHLEN];
 
-	n = snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, luser);
+	n = snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, l_user);
 	if (n < 0 || (u_int)n >= sizeof(tmp)) {
 		syslog(LOG_ERR, "provided banned directory line too long (%s)",
 		    luserdir);
@@ -555,7 +619,7 @@ check_luser(char *luserdir, char *luser)
 		 * tell what they can do and where they can go.
 		 */
 		syslog(LOG_INFO, "denied access to %s: %s exists",
-		    luser, tmp);
+		    l_user, tmp);
 
 		/* reuse tmp */
 		strlcpy(tmp, "\n\n-**- Sorry, you have been banned! -**-\n\n",
@@ -581,7 +645,7 @@ static int
 remove_stale_rulesets(void)
 {
 	struct pfioc_ruleset	 prs;
-	u_int32_t		 nr, mnr;
+	u_int32_t		 nr;
 
 	memset(&prs, 0, sizeof(prs));
 	strlcpy(prs.path, anchorname, sizeof(prs.path));
@@ -592,13 +656,12 @@ remove_stale_rulesets(void)
 			return (1);
 	}
 
-	mnr = prs.nr;
-	nr = 0;
-	while (nr < mnr) {
+	nr = prs.nr;
+	while (nr) {
 		char	*s, *t;
 		pid_t	 pid;
 
-		prs.nr = nr;
+		prs.nr = nr - 1;
 		if (ioctl(dev, DIOCGETRULESET, &prs))
 			return (1);
 		errno = 0;
@@ -610,119 +673,159 @@ remove_stale_rulesets(void)
 		if (!prs.name[0] || errno ||
 		    (*s && (t == prs.name || *s != ')')))
 			return (1);
-		if (kill(pid, 0) && errno != EPERM) {
-			int			i;
-			struct pfioc_trans_e	t_e[PF_RULESET_MAX+1];
-			struct pfioc_trans	t;
-
-			bzero(&t, sizeof(t));
-			bzero(t_e, sizeof(t_e));
-			t.size = PF_RULESET_MAX+1;
-			t.esize = sizeof(t_e[0]);
-			t.array = t_e;
-			for (i = 0; i < PF_RULESET_MAX+1; ++i) {
-				t_e[i].rs_num = i;
-				snprintf(t_e[i].anchor, sizeof(t_e[i].anchor),
-				    "%s/%s", anchorname, prs.name);
-			}
-			t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE;
-			if ((ioctl(dev, DIOCXBEGIN, &t) ||
-			    ioctl(dev, DIOCXCOMMIT, &t)) &&
-			    errno != EINVAL)
+		if ((kill(pid, 0) && errno != EPERM) || pid == getpid()) {
+			if (recursive_ruleset_purge(anchorname, prs.name))
 				return (1);
-			mnr--;
-		} else
-			nr++;
+		}
+		nr--;
 	}
 	return (0);
 }
 
+static int
+recursive_ruleset_purge(char *an, char *rs)
+{
+	struct pfioc_trans_e     *t_e = NULL;
+	struct pfioc_trans	 *t = NULL;
+	struct pfioc_ruleset	 *prs = NULL;
+	int			  i;
+
+
+	/* purge rules */
+	errno = 0;
+	if ((t = calloc(1, sizeof(struct pfioc_trans))) == NULL)
+		goto no_mem;
+	if ((t_e = calloc(PF_RULESET_MAX+1,
+	    sizeof(struct pfioc_trans_e))) == NULL)
+		goto no_mem;
+	t->size = PF_RULESET_MAX+1;
+	t->esize = sizeof(struct pfioc_trans_e);
+	t->array = t_e;
+	for (i = 0; i < PF_RULESET_MAX+1; ++i) {
+		t_e[i].rs_num = i;
+		snprintf(t_e[i].anchor, sizeof(t_e[i].anchor), "%s/%s", an, rs);
+	}
+	t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE;
+	if ((ioctl(dev, DIOCXBEGIN, t) ||
+	    ioctl(dev, DIOCXCOMMIT, t)) &&
+	    errno != EINVAL)
+		goto cleanup;
+
+	/* purge any children */
+	if ((prs = calloc(1, sizeof(struct pfioc_ruleset))) == NULL)
+		goto no_mem;
+	snprintf(prs->path, sizeof(prs->path), "%s/%s", an, rs);
+	if (ioctl(dev, DIOCGETRULESETS, prs)) {
+		if (errno != EINVAL)
+			goto cleanup;
+		errno = 0;
+	} else {
+		int nr = prs->nr;
+
+		while (nr) {
+			prs->nr = 0;
+			if (ioctl(dev, DIOCGETRULESET, prs))
+				goto cleanup;
+
+			if (recursive_ruleset_purge(prs->path, prs->name))
+				goto cleanup;
+			nr--;
+		}
+	}
+
+no_mem:
+	if (errno == ENOMEM)
+		syslog(LOG_ERR, "calloc failed");
+
+cleanup:
+	free(t);
+	free(t_e);
+	free(prs);
+	return (errno);
+}
+
 /*
  * Add/remove filter entries for user "luser" from ip "ipsrc"
  */
 static int
-change_filter(int add, const char *luser, const char *ipsrc)
+change_filter(int add, const char *l_user, const char *ip_src)
 {
-	char	*pargv[13] = {
-		"pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
-		"-D", "user_ip=X", "-D", "user_id=X", "-f",
-		"file", NULL
-	};
 	char	*fdpath = NULL, *userstr = NULL, *ipstr = NULL;
 	char	*rsn = NULL, *fn = NULL;
 	pid_t	pid;
 	gid_t   gid;
 	int	s;
 
-	if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
-		syslog(LOG_ERR, "invalid luser/ipsrc");
-		goto error;
-	}
-
-	if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)
-		goto no_mem;
-	if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1)
-		goto no_mem;
-	if (asprintf(&ipstr, "user_ip=%s", ipsrc) == -1)
-		goto no_mem;
-	if (asprintf(&userstr, "user_id=%s", luser) == -1)
-		goto no_mem;
-
 	if (add) {
 		struct stat sb;
+		char *pargv[13] = {
+			"pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
+			"-D", "user_id=X", "-D", "user_ip=X", "-f", "file", NULL
+		};
+
+		if (l_user == NULL || !l_user[0] || ip_src == NULL || !ip_src[0]) {
+			syslog(LOG_ERR, "invalid luser/ipsrc");
+			goto error;
+		}
 
-		if (asprintf(&fn, "%s/%s/authpf.rules", PATH_USER_DIR, luser)
-		    == -1)
+		if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)
+			goto no_mem;
+		if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1)
+			goto no_mem;
+		if (asprintf(&ipstr, "user_ip=%s", ip_src) == -1)
+			goto no_mem;
+		if (asprintf(&userstr, "user_id=%s", l_user) == -1)
+			goto no_mem;
+		if (asprintf(&fn, "%s/%s/authpf.rules",
+		    PATH_USER_DIR, l_user) == -1)
 			goto no_mem;
 		if (stat(fn, &sb) == -1) {
 			free(fn);
 			if ((fn = strdup(PATH_PFRULES)) == NULL)
 				goto no_mem;
 		}
-	}
-	pargv[2] = fdpath;
-	pargv[5] = rsn;
-	pargv[7] = userstr;
-	pargv[9] = ipstr;
-	if (!add)
-		pargv[11] = "/dev/null";
-	else
-		pargv[11] = fn;
-
-	switch (pid = fork()) {
-	case -1:
-		syslog(LOG_ERR, "fork failed");
-		goto error;
-	case 0:
-		/* revoke group privs before exec */
-		gid = getgid();
-		if (setregid(gid, gid) == -1) {
-			err(1, "setregid");
+		pargv[2] = fdpath;
+		pargv[5] = rsn;
+		pargv[7] = userstr;
+		if (user_ip) {
+			pargv[9] = ipstr;
+			pargv[11] = fn;
+		} else {
+			pargv[8] = "-f";
+			pargv[9] = fn;
+			pargv[10] = NULL;
 		}
-		execvp(PATH_PFCTL, pargv);
-		warn("exec of %s failed", PATH_PFCTL);
-		_exit(1);
-	}
 
-	/* parent */
-	waitpid(pid, &s, 0);
-	if (s != 0) {
-		syslog(LOG_ERR, "pfctl exited abnormally");
-		goto error;
-	}
+		switch (pid = fork()) {
+		case -1:
+			syslog(LOG_ERR, "fork failed");
+			goto error;
+		case 0:
+			/* revoke group privs before exec */
+			gid = getgid();
+			if (setregid(gid, gid) == -1) {
+				err(1, "setregid");
+			}
+			execvp(PATH_PFCTL, pargv);
+			warn("exec of %s failed", PATH_PFCTL);
+			_exit(1);
+		}
+
+		/* parent */
+		waitpid(pid, &s, 0);
+		if (s != 0) {
+			syslog(LOG_ERR, "pfctl exited abnormally");
+			goto error;
+		}
 
-	if (add) {
 		gettimeofday(&Tstart, NULL);
-		syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser);
+		syslog(LOG_INFO, "allowing %s, user %s", ip_src, l_user);
 	} else {
+		remove_stale_rulesets();
+
 		gettimeofday(&Tend, NULL);
-#ifdef __FreeBSD__
-		syslog(LOG_INFO, "removed %s, user %s - duration %jd seconds",
-		    ipsrc, luser, (intmax_t)(Tend.tv_sec - Tstart.tv_sec));
-#else
-		syslog(LOG_INFO, "removed %s, user %s - duration %ld seconds",
-		    ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
-#endif
+		syslog(LOG_INFO, "removed %s, user %s - duration %ju seconds",
+		    ip_src, l_user, (uintmax_t)(Tend.tv_sec - Tstart.tv_sec));
 	}
 	return (0);
 no_mem:
@@ -740,7 +843,7 @@ error:
  * Add/remove this IP from the "authpf_users" table.
  */
 static int
-change_table(int add, const char *ipsrc)
+change_table(int add, const char *ip_src)
 {
 	struct pfioc_table	io;
 	struct pfr_addr		addr;
@@ -753,12 +856,12 @@ change_table(int add, const char *ipsrc)
 	io.pfrio_size = 1;
 
 	bzero(&addr, sizeof(addr));
-	if (ipsrc == NULL || !ipsrc[0])
+	if (ip_src == NULL || !ip_src[0])
 		return (-1);
-	if (inet_pton(AF_INET, ipsrc, &addr.pfra_ip4addr) == 1) {
+	if (inet_pton(AF_INET, ip_src, &addr.pfra_ip4addr) == 1) {
 		addr.pfra_af = AF_INET;
 		addr.pfra_net = 32;
-	} else if (inet_pton(AF_INET6, ipsrc, &addr.pfra_ip6addr) == 1) {
+	} else if (inet_pton(AF_INET6, ip_src, &addr.pfra_ip6addr) == 1) {
 		addr.pfra_af = AF_INET6;
 		addr.pfra_net = 128;
 	} else {
@@ -769,7 +872,7 @@ change_table(int add, const char *ipsrc)
 	if (ioctl(dev, add ? DIOCRADDADDRS : DIOCRDELADDRS, &io) &&
 	    errno != ESRCH) {
 		syslog(LOG_ERR, "cannot %s %s from table %s: %s",
-		    add ? "add" : "remove", ipsrc, tablename,
+		    add ? "add" : "remove", ip_src, tablename,
 		    strerror(errno));
 		return (-1);
 	}
@@ -821,7 +924,7 @@ authpf_kill_states(void)
 
 /* signal handler that makes us go away properly */
 static void
-need_death(int signo)
+need_death(int signo __unused)
 {
 	want_death = 1;
 }
@@ -840,11 +943,12 @@ do_death(int active)
 
 	if (active) {
 		change_filter(0, luser, ipsrc);
-		change_table(0, ipsrc);
-		authpf_kill_states();
-		remove_stale_rulesets();
+		if (user_ip) {
+			change_table(0, ipsrc);
+			authpf_kill_states();
+		}
 	}
-	if (pidfile[0] && (pidfp != NULL))
+	if (pidfile[0] && pidfd != -1)
 		if (unlink(pidfile) == -1)
 			syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
 	exit(ret);
diff --git a/contrib/pf/authpf/pathnames.h b/contrib/pf/authpf/pathnames.h
index 358bfd0..e02cf77 100644
--- a/contrib/pf/authpf/pathnames.h
+++ b/contrib/pf/authpf/pathnames.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pathnames.h,v 1.7 2004/04/25 18:40:42 beck Exp $	*/
+/*	$OpenBSD: pathnames.h,v 1.8 2008/02/14 01:49:17 mcbride Exp $	*/
 
 /*
  * Copyright (C) 2002 Chris Kuethe (ckuethe@ualberta.ca)
@@ -35,4 +35,5 @@
 #define PATH_DEVFILE		"/dev/pf"
 #define PATH_PIDFILE		"/var/authpf"
 #define PATH_AUTHPF_SHELL	"/usr/sbin/authpf"
+#define PATH_AUTHPF_SHELL_NOIP	"/usr/sbin/authpf-noip"
 #define PATH_PFCTL		"/sbin/pfctl"
diff --git a/contrib/pf/ftp-proxy/filter.c b/contrib/pf/ftp-proxy/filter.c
index f86429d..f575db1 100644
--- a/contrib/pf/ftp-proxy/filter.c
+++ b/contrib/pf/ftp-proxy/filter.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: filter.c,v 1.5 2006/12/01 07:31:21 camield Exp $ */
+/*	$OpenBSD: filter.c,v 1.8 2008/06/13 07:25:26 claudio Exp $ */
 
 /*
  * Copyright (c) 2004, 2005 Camiel Dobbelaar, 
@@ -53,7 +53,7 @@ static struct pfioc_rule	pfr;
 static struct pfioc_trans	pft;
 static struct pfioc_trans_e	pfte[TRANS_SIZE];
 static int dev, rule_log;
-static char *qname;
+static const char *qname, *tagname;
 
 int
 add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src,
@@ -159,11 +159,12 @@ do_rollback(void)
 }
 
 void
-init_filter(char *opt_qname, int opt_verbose)
+init_filter(const char *opt_qname, const char *opt_tagname, int opt_verbose)
 {
 	struct pf_status status;
 
 	qname = opt_qname;
+	tagname = opt_tagname;
 
 	if (opt_verbose == 1)
 		rule_log = PF_LOG;
@@ -172,7 +173,7 @@ init_filter(char *opt_qname, int opt_verbose)
 
 	dev = open("/dev/pf", O_RDWR);	
 	if (dev == -1)
-		err(1, "/dev/pf");
+		err(1, "open /dev/pf");
 	if (ioctl(dev, DIOCGETSTATUS, &status) == -1)
 		err(1, "DIOCGETSTATUS");
 	if (!status.running)
@@ -280,9 +281,9 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
 	switch (rs_num) {
 	case PF_RULESET_FILTER:
 		/*
-		 * pass quick [log] inet[6] proto tcp \
+		 * pass [quick] [log] inet[6] proto tcp \
 		 *     from $src to $dst port = $d_port flags S/SA keep state
-		 *     (max 1) [queue qname]
+		 *     (max 1) [queue qname] [tag tagname]
 		 */
 		pfr.rule.action = PF_PASS;
 		pfr.rule.quick = 1;
@@ -293,6 +294,11 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
 		pfr.rule.max_states = 1;
 		if (qname != NULL)
 			strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
+		if (tagname != NULL) {
+			pfr.rule.quick = 0;
+			strlcpy(pfr.rule.tagname, tagname,
+                                sizeof pfr.rule.tagname);
+		}
 		break;
 	case PF_RULESET_NAT:
 		/*
diff --git a/contrib/pf/ftp-proxy/filter.h b/contrib/pf/ftp-proxy/filter.h
index 6779c59..3b48898 100644
--- a/contrib/pf/ftp-proxy/filter.h
+++ b/contrib/pf/ftp-proxy/filter.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: filter.h,v 1.3 2005/06/07 14:12:07 camield Exp $ */
+/*	$OpenBSD: filter.h,v 1.4 2007/08/01 09:31:41 henning Exp $ */
 
 /*
  * Copyright (c) 2004, 2005 Camiel Dobbelaar, 
@@ -26,6 +26,6 @@ int add_rdr(u_int32_t, struct sockaddr *, struct sockaddr *, u_int16_t,
     struct sockaddr *, u_int16_t);
 int do_commit(void);
 int do_rollback(void);
-void init_filter(char *, int);
+void init_filter(const char *, const char *, int);
 int prepare_commit(u_int32_t);
 int server_lookup(struct sockaddr *, struct sockaddr *, struct sockaddr *);
diff --git a/contrib/pf/ftp-proxy/ftp-proxy.8 b/contrib/pf/ftp-proxy/ftp-proxy.8
index 69c848e..d4dd030 100644
--- a/contrib/pf/ftp-proxy/ftp-proxy.8
+++ b/contrib/pf/ftp-proxy/ftp-proxy.8
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: ftp-proxy.8,v 1.7 2006/12/30 13:01:54 camield Exp $
+.\"	$OpenBSD: ftp-proxy.8,v 1.11 2008/02/26 18:52:53 henning Exp $
 .\"
 .\" Copyright (c) 2004, 2005 Camiel Dobbelaar, 
 .\"
@@ -16,14 +16,15 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 28, 2004
+.Dd February 26, 2008
 .Dt FTP-PROXY 8
 .Os
 .Sh NAME
 .Nm ftp-proxy
 .Nd Internet File Transfer Protocol proxy daemon
 .Sh SYNOPSIS
-.Nm ftp-proxy
+.Nm
+.Bk -words
 .Op Fl 6Adrv
 .Op Fl a Ar address
 .Op Fl b Ar address
@@ -33,7 +34,9 @@
 .Op Fl p Ar port
 .Op Fl q Ar queue
 .Op Fl R Ar address
+.Op Fl T Ar tag
 .Op Fl t Ar timeout
+.Ek
 .Sh DESCRIPTION
 .Nm
 is a proxy for the Internet File Transfer Protocol.
@@ -58,7 +61,7 @@ facility for this.
 Assuming the FTP control connection is from $client to $server, the
 proxy connected to the server using the $proxy source address, and
 $port is negotiated, then
-.Nm ftp-proxy
+.Nm
 adds the following rules to the various anchors.
 (These example rules use inet, but the proxy also supports inet6.)
 .Pp
@@ -130,6 +133,20 @@ connections to another proxy.
 .It Fl r
 Rewrite sourceport to 20 in active mode to suit ancient clients that insist
 on this RFC property.
+.It Fl T Ar tag
+The filter rules will add tag
+.Ar tag
+to data connections, and not match quick.
+This way alternative rules that use the
+.Ar tagged
+keyword can be implemented following the
+.Nm
+anchor.
+These rules can use special
+.Xr pf 4
+features like route-to, reply-to, label, rtable, overload, etc. that
+.Nm
+does not implement itself.
 .It Fl t Ar timeout
 Number of seconds that the control connection can be idle, before the
 proxy will disconnect.
@@ -172,7 +189,7 @@ does not allow the ruleset to be modified if the system is running at a
 .Xr securelevel 7
 higher than 1.
 At that level
-.Nm ftp-proxy
+.Nm
 cannot add rules to the anchors and FTP data connections may get blocked.
 .Pp
 Negotiated data connection ports below 1024 are not allowed.
@@ -181,5 +198,5 @@ The negotiated IP address for active modes is ignored for security
 reasons.
 This makes third party file transfers impossible.
 .Pp
-.Nm ftp-proxy
+.Nm
 chroots to "/var/empty" and changes to user "proxy" to drop privileges.
diff --git a/contrib/pf/ftp-proxy/ftp-proxy.c b/contrib/pf/ftp-proxy/ftp-proxy.c
index 06c8487..26de75a 100644
--- a/contrib/pf/ftp-proxy/ftp-proxy.c
+++ b/contrib/pf/ftp-proxy/ftp-proxy.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ftp-proxy.c,v 1.13 2006/12/30 13:24:00 camield Exp $ */
+/*	$OpenBSD: ftp-proxy.c,v 1.19 2008/06/13 07:25:26 claudio Exp $ */
 
 /*
  * Copyright (c) 2004, 2005 Camiel Dobbelaar, 
@@ -61,6 +61,14 @@ __FBSDID("$FreeBSD$");
 #define PF_NAT_PROXY_PORT_LOW	50001
 #define PF_NAT_PROXY_PORT_HIGH	65535
 
+#ifndef LIST_END
+#define LIST_END(a)     NULL
+#endif
+
+#ifndef getrtable
+#define getrtable(a)    0
+#endif
+
 #define	sstosa(ss)	((struct sockaddr *)(ss))
 
 enum { CMD_NONE = 0, CMD_PORT, CMD_EPRT, CMD_PASV, CMD_EPSV };
@@ -94,7 +102,7 @@ int	client_parse_cmd(struct session *s);
 void	client_read(struct bufferevent *, void *);
 int	drop_privs(void);
 void	end_session(struct session *);
-int	exit_daemon(void);
+void	exit_daemon(void);
 int	getline(char *, size_t *);
 void	handle_connection(const int, short, void *);
 void	handle_signal(int, short, void *);
@@ -105,6 +113,7 @@ u_int16_t pick_proxy_port(void);
 void	proxy_reply(int, struct sockaddr *, u_int16_t);
 void	server_error(struct bufferevent *, short, void *);
 int	server_parse(struct session *s);
+int	allow_data_connection(struct session *s);
 void	server_read(struct bufferevent *, void *);
 const char *sock_ntop(struct sockaddr *);
 void	usage(void);
@@ -115,14 +124,14 @@ size_t linelen;
 char ntop_buf[NTOP_BUFS][INET6_ADDRSTRLEN];
 
 struct sockaddr_storage fixed_server_ss, fixed_proxy_ss;
-char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port,
-    *qname;
+const char *fixed_server, *fixed_server_port, *fixed_proxy, *listen_ip, *listen_port,
+    *qname, *tagname;
 int anonymous_only, daemonize, id_count, ipv6_mode, loglevel, max_sessions,
     rfc_mode, session_count, timeout, verbose;
 extern char *__progname;
 
 void
-client_error(struct bufferevent *bufev, short what, void *arg)
+client_error(struct bufferevent *bufev __unused, short what, void *arg)
 {
 	struct session *s = arg;
 
@@ -152,8 +161,19 @@ client_parse(struct session *s)
 		return (1);
 
 	if (linebuf[0] == 'P' || linebuf[0] == 'p' ||
-	    linebuf[0] == 'E' || linebuf[0] == 'e')
-		return (client_parse_cmd(s));
+	    linebuf[0] == 'E' || linebuf[0] == 'e') {
+		if (!client_parse_cmd(s))
+			return (0);
+
+		/*
+		 * Allow active mode connections immediately, instead of
+		 * waiting for a positive reply from the server.  Some
+		 * rare servers/proxies try to probe or setup the data
+		 * connection before an actual transfer request.
+		 */
+		if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT)
+			return (allow_data_connection(s));
+	}
 	
 	if (anonymous_only && (linebuf[0] == 'U' || linebuf[0] == 'u'))
 		return (client_parse_anon(s));
@@ -220,14 +240,14 @@ void
 client_read(struct bufferevent *bufev, void *arg)
 {
 	struct session	*s = arg;
-	size_t		 buf_avail, read;
+	size_t		 buf_avail, clientread;
 	int		 n;
 
 	do {
 		buf_avail = sizeof s->cbuf - s->cbuf_valid;
-		read = bufferevent_read(bufev, s->cbuf + s->cbuf_valid,
+		clientread = bufferevent_read(bufev, s->cbuf + s->cbuf_valid,
 		    buf_avail);
-		s->cbuf_valid += read;
+		s->cbuf_valid += clientread;
 
 		while ((n = getline(s->cbuf, &s->cbuf_valid)) > 0) {
 			logmsg(LOG_DEBUG, "#%d client: %s", s->id, linebuf);
@@ -244,7 +264,7 @@ client_read(struct bufferevent *bufev, void *arg)
 			end_session(s);
 			return;
 		}
-	} while (read == buf_avail);
+	} while (clientread == buf_avail);
 }
 
 int
@@ -269,10 +289,16 @@ drop_privs(void)
 void
 end_session(struct session *s)
 {
-	int err;
+	int serr;
 
 	logmsg(LOG_INFO, "#%d ending session", s->id);
 
+	/* Flush output buffers. */
+	if (s->client_bufev && s->client_fd != -1)
+		evbuffer_write(s->client_bufev->output, s->client_fd);
+	if (s->server_bufev && s->server_fd != -1)
+		evbuffer_write(s->server_bufev->output, s->server_fd);
+
 	if (s->client_fd != -1)
 		close(s->client_fd);
 	if (s->server_fd != -1)
@@ -284,33 +310,29 @@ end_session(struct session *s)
 		bufferevent_free(s->server_bufev);
 
 	/* Remove rulesets by commiting empty ones. */
-	err = 0;
+	serr = 0;
 	if (prepare_commit(s->id) == -1)
-		err = errno;
+		serr = errno;
 	else if (do_commit() == -1) {
-		err = errno;
+		serr = errno;
 		do_rollback();
 	}
-	if (err)
+	if (serr)
 		logmsg(LOG_ERR, "#%d pf rule removal failed: %s", s->id,
-		    strerror(err));
+		    strerror(serr));
 
 	LIST_REMOVE(s, entry);
 	free(s);
 	session_count--;
 }
 
-int
+void
 exit_daemon(void)
 {
 	struct session *s, *next;
 
-#ifdef __FreeBSD__
-	LIST_FOREACH_SAFE(s, &sessions, entry, next) {
-#else
 	for (s = LIST_FIRST(&sessions); s != LIST_END(&sessions); s = next) {
 		next = LIST_NEXT(s, entry);
-#endif
 		end_session(s);
 	}
 
@@ -318,9 +340,6 @@ exit_daemon(void)
 		closelog();
 
 	exit(0);
-
-	/* NOTREACHED */
-	return (-1);
 }
 
 int
@@ -361,7 +380,7 @@ getline(char *buf, size_t *valid)
 }
 
 void
-handle_connection(const int listen_fd, short event, void *ev)
+handle_connection(const int listen_fd, short event __unused, void *ev __unused)
 {
 	struct sockaddr_storage tmp_ss;
 	struct sockaddr *client_sa, *server_sa, *fixed_server_sa;
@@ -508,13 +527,13 @@ handle_connection(const int listen_fd, short event, void *ev)
 }
 
 void
-handle_signal(int sig, short event, void *arg)
+handle_signal(int sig, short event __unused, void *arg __unused)
 {
 	/*
 	 * Signal handler rules don't apply, libevent decouples for us.
 	 */
 
-	logmsg(LOG_ERR, "%s exiting on signal %d", __progname, sig);
+	logmsg(LOG_ERR, "exiting on signal %d", sig);
 
 	exit_daemon();
 }
@@ -567,10 +586,7 @@ logmsg(int pri, const char *message, ...)
 		/* We don't care about truncation. */
 		vsnprintf(buf, sizeof buf, message, ap);
 #ifdef __FreeBSD__
-		/* XXX: strnvis might be nice to have */
-		strvisx(visbuf, buf,
-		    MIN((sizeof(visbuf) / 4) - 1, strlen(buf)),
-		    VIS_CSTYLE | VIS_NL);
+		strvis(visbuf, buf, VIS_CSTYLE | VIS_NL);
 #else
 		strnvis(visbuf, buf, sizeof visbuf, VIS_CSTYLE | VIS_NL);
 #endif
@@ -602,6 +618,7 @@ main(int argc, char *argv[])
 	max_sessions	= 100;
 	qname		= NULL;
 	rfc_mode	= 0;
+	tagname		= NULL;
 	timeout		= 24 * 3600;
 	verbose		= 0;
 
@@ -609,7 +626,7 @@ main(int argc, char *argv[])
 	id_count	= 1;
 	session_count	= 0;
 
-	while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rt:v")) != -1) {
+	while ((ch = getopt(argc, argv, "6Aa:b:D:dm:P:p:q:R:rT:t:v")) != -1) {
 		switch (ch) {
 		case '6':
 			ipv6_mode = 1;
@@ -654,6 +671,11 @@ main(int argc, char *argv[])
 		case 'r':
 			rfc_mode = 1;
 			break;
+		case 'T':
+			if (strlen(optarg) >= PF_TAG_NAME_SIZE)
+				errx(1, "tagname too long");
+			tagname = optarg;
+			break;
 		case 't':
 			timeout = strtonum(optarg, 0, 86400, &errstr);
 			if (errstr)
@@ -734,7 +756,7 @@ main(int argc, char *argv[])
 	freeaddrinfo(res);
 
 	/* Initialize pf. */
-	init_filter(qname, verbose);
+	init_filter(qname, tagname, verbose);
 
 	if (daemonize) {
 		if (daemon(0, 0) == -1)
@@ -830,14 +852,15 @@ u_int16_t
 pick_proxy_port(void)
 {
 	/* Random should be good enough for avoiding port collisions. */
-	return (IPPORT_HIFIRSTAUTO + (arc4random() %
-	    (IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO)));
+	return (IPPORT_HIFIRSTAUTO +
+	    arc4random_uniform(IPPORT_HILASTAUTO - IPPORT_HIFIRSTAUTO));
 }
 
 void
 proxy_reply(int cmd, struct sockaddr *sa, u_int16_t port)
 {
-	int i, r;
+	u_int i;
+	int r = 0;
 
 	switch (cmd) {
 	case CMD_PORT:
@@ -864,7 +887,7 @@ proxy_reply(int cmd, struct sockaddr *sa, u_int16_t port)
 		break;
 	}
 
-	if (r < 0 || r >= sizeof linebuf) {
+	if (r < 0 || ((u_int)r) >= sizeof linebuf) {
 		logmsg(LOG_ERR, "proxy_reply failed: %d", r);
 		linebuf[0] = '\0';
 		linelen = 0;
@@ -881,7 +904,7 @@ proxy_reply(int cmd, struct sockaddr *sa, u_int16_t port)
 }
 
 void
-server_error(struct bufferevent *bufev, short what, void *arg)
+server_error(struct bufferevent *bufev __unused, short what, void *arg)
 {
 	struct session *s = arg;
 
@@ -902,12 +925,26 @@ server_error(struct bufferevent *bufev, short what, void *arg)
 int
 server_parse(struct session *s)
 {
-	struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
-	int prepared = 0;
-
 	if (s->cmd == CMD_NONE || linelen < 4 || linebuf[0] != '2')
 		goto out;
 
+	if ((s->cmd == CMD_PASV && strncmp("227 ", linebuf, 4) == 0) ||
+	    (s->cmd == CMD_EPSV && strncmp("229 ", linebuf, 4) == 0))
+		return (allow_data_connection(s));
+
+ out:
+	s->cmd = CMD_NONE;
+	s->port = 0;
+
+	return (1);
+}
+
+int
+allow_data_connection(struct session *s)
+{
+	struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
+	int prepared = 0;
+
 	/*
 	 * The pf rules below do quite some NAT rewriting, to keep up
 	 * appearances.  Points to keep in mind:
@@ -932,8 +969,7 @@ server_parse(struct session *s)
 		orig_sa = sstosa(&s->server_ss);
 
 	/* Passive modes. */
-	if ((s->cmd == CMD_PASV && strncmp("227 ", linebuf, 4) == 0) ||
-	    (s->cmd == CMD_EPSV && strncmp("229 ", linebuf, 4) == 0)) {
+	if (s->cmd == CMD_PASV || s->cmd == CMD_EPSV) {
 		s->port = parse_port(s->cmd);
 		if (s->port < MIN_PORT) {
 			logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id,
@@ -974,8 +1010,7 @@ server_parse(struct session *s)
 	}
 
 	/* Active modes. */
-	if ((s->cmd == CMD_PORT || s->cmd == CMD_EPRT) &&
-	    strncmp("200 ", linebuf, 4) == 0) {
+	if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) {
 		logmsg(LOG_INFO, "#%d active: server to client port %d"
 		    " via port %d", s->id, s->port, s->proxy_port);
 
@@ -1025,7 +1060,6 @@ server_parse(struct session *s)
 			goto fail;
 	}
 
- out:
 	s->cmd = CMD_NONE;
 	s->port = 0;
 
@@ -1042,16 +1076,16 @@ void
 server_read(struct bufferevent *bufev, void *arg)
 {
 	struct session	*s = arg;
-	size_t		 buf_avail, read;
+	size_t		 buf_avail, srvread;
 	int		 n;
 
 	bufferevent_settimeout(bufev, timeout, 0);
 
 	do {
 		buf_avail = sizeof s->sbuf - s->sbuf_valid;
-		read = bufferevent_read(bufev, s->sbuf + s->sbuf_valid,
+		srvread = bufferevent_read(bufev, s->sbuf + s->sbuf_valid,
 		    buf_avail);
-		s->sbuf_valid += read;
+		s->sbuf_valid += srvread;
 
 		while ((n = getline(s->sbuf, &s->sbuf_valid)) > 0) {
 			logmsg(LOG_DEBUG, "#%d server: %s", s->id, linebuf);
@@ -1068,7 +1102,7 @@ server_read(struct bufferevent *bufev, void *arg)
 			end_session(s);
 			return;
 		}
-	} while (read == buf_avail);
+	} while (srvread == buf_avail);
 }
 
 const char *
@@ -1102,6 +1136,7 @@ usage(void)
 {
 	fprintf(stderr, "usage: %s [-6Adrv] [-a address] [-b address]"
 	    " [-D level] [-m maxsessions]\n                 [-P port]"
-	    " [-p port] [-q queue] [-R address] [-t timeout]\n", __progname);
+	    " [-p port] [-q queue] [-R address] [-T tag]\n"
+            "                 [-t timeout]\n", __progname);
 	exit(1);
 }
diff --git a/contrib/pf/man/pf.4 b/contrib/pf/man/pf.4
index 16e74ab..75e421d 100644
--- a/contrib/pf/man/pf.4
+++ b/contrib/pf/man/pf.4
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: pf.4,v 1.58 2007/02/09 11:39:06 henning Exp $
+.\"	$OpenBSD: pf.4,v 1.62 2008/09/10 14:57:37 jmc Exp $
 .\"
 .\" Copyright (C) 2001, Kjell Wooding.  All rights reserved.
 .\"
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 7, 2005
+.Dd September 10 2008
 .Dt PF 4
 .Os
 .Sh NAME
@@ -294,14 +294,17 @@ if another process is concurrently updating a ruleset.
 Add a state entry.
 .Bd -literal
 struct pfioc_state {
-	u_int32_t	 nr;
-	struct pf_state	 state;
+	struct pfsync_state	state;
 };
 .Ed
 .It Dv DIOCGETSTATE Fa "struct pfioc_state *ps"
-Extract the entry with the specified number
-.Va nr
-from the state table.
+Extract the entry identified by the
+.Va id
+and
+.Va creatorid
+fields of the
+.Va state
+structure from the state table.
 .It Dv DIOCKILLSTATES Fa "struct pfioc_state_kill *psk"
 Remove matching entries from the state table.
 This ioctl returns the number of killed states in
@@ -1049,12 +1052,14 @@ internal interface description.
 The filtering process is the same as for
 .Dv DIOCIGETIFACES .
 .Bd -literal
-#define PFI_IFLAG_SKIP		0x0100	/* skip filtering on interface */
+#define PFI_IFLAG_SKIP	0x0100	/* skip filtering on interface */
 .Ed
 .It Dv DIOCCLRIFFLAG Fa "struct pfioc_iface *io"
 Works as
 .Dv DIOCSETIFFLAG
 above but clears the flags.
+.It Dv DIOCKILLSRCNODES Fa "struct pfioc_iface *io"
+Explicitly remove source tracking nodes.
 .El
 .Sh FILES
 .Bl -tag -width /dev/pf -compact
@@ -1133,6 +1138,7 @@ main(int argc, char *argv[])
 .Xr altq 4 ,
 .Xr if_bridge 4 ,
 .Xr pflog 4 ,
+.Xr pflow 4 ,
 .Xr pfsync 4 ,
 .Xr pfctl 8 ,
 .Xr altq 9
diff --git a/contrib/pf/man/pf.conf.5 b/contrib/pf/man/pf.conf.5
index 98c3d0e..dfec264 100644
--- a/contrib/pf/man/pf.conf.5
+++ b/contrib/pf/man/pf.conf.5
@@ -1,5 +1,5 @@
-.\"	$FreeBSD$
-.\"	$OpenBSD: pf.conf.5,v 1.393 2008/02/11 07:46:32 jmc Exp $
+.\"    $FreeBSD$
+.\"	$OpenBSD: pf.conf.5,v 1.406 2009/01/31 19:37:12 sobrado Exp $
 .\"
 .\" Copyright (c) 2002, Daniel Hartmeier
 .\" All rights reserved.
@@ -28,7 +28,7 @@
 .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd June 10, 2008
+.Dd January 31 2009
 .Dt PF.CONF 5
 .Os
 .Sh NAME
@@ -79,6 +79,17 @@ By default
 enforces this order (see
 .Ar set require-order
 below).
+.Pp
+Comments can be put anywhere in the file using a hash mark
+.Pq Sq # ,
+and extend to the end of the current line.
+.Pp
+Additional configuration files can be included with the
+.Ic include
+keyword, for example:
+.Bd -literal -offset indent
+include "/etc/pf/sub.filter.conf"
+.Ed
 .Sh MACROS
 Macros can be defined that will later be expanded in context.
 Macro names must start with a letter, and may contain letters, digits
@@ -154,7 +165,7 @@ A table initialized with the empty list,
 will be cleared on load.
 .El
 .Pp
-Tables may be defined with the following two attributes:
+Tables may be defined with the following attributes:
 .Bl -tag -width persist
 .It Ar persist
 The
@@ -173,6 +184,11 @@ can be used to add or remove addresses from the table at any time, even
 when running with
 .Xr securelevel 7
 = 2.
+.It Ar counters
+The
+.Ar counters
+flag enables per-address packet and byte counters which can be displayed with
+.Xr pfctl 8 .
 .El
 .Pp
 For example,
@@ -328,7 +344,8 @@ With 9000 state table entries, the timeout values are scaled to 50%
 (tcp.first 60, tcp.established 43200).
 .Pp
 .It Ar set loginterface
-Enable collection of packet and byte count statistics for the given interface.
+Enable collection of packet and byte count statistics for the given
+interface or interface group.
 These statistics can be viewed using
 .Bd -literal -offset indent
 # pfctl -s info
@@ -403,9 +420,10 @@ set limit { states 20000, frags 20000, src-nodes 2000 }
 .Bl -tag -width xxxxxxxx -compact
 .It Ar none
 Disable the ruleset optimizer.
-This is the default behaviour.
 .It Ar basic
-Enable basic ruleset optimization, which does four things to improve the
+Enable basic ruleset optimization.
+This is the default behaviour.
+Basic ruleset optimization does four things to improve the
 performance of ruleset evaluations:
 .Pp
 .Bl -enum -compact
@@ -500,6 +518,16 @@ For example:
 .Bd -literal -offset indent
 set state-policy if-bound
 .Ed
+.It Ar set state-defaults
+The
+.Ar state-defaults
+option sets the state options for states created from rules
+without an explicit
+.Ar keep state .
+For example:
+.Bd -literal -offset indent
+set state-defaults pflow, no-sync
+.Ed
 .It Ar set hostid
 The 32-bit
 .Ar hostid
@@ -617,6 +645,19 @@ modifier to ensure unique IP identifiers.
 Enforces a minimum TTL for matching IP packets.
 .It Ar max-mss Aq Ar number
 Enforces a maximum MSS for matching TCP packets.
+.It Xo Ar set-tos Aq Ar string
+.No \*(Ba Aq Ar number
+.Xc
+Enforces a
+.Em TOS
+for matching IP packets.
+.Em TOS
+may be
+given as one of
+.Ar lowdelay ,
+.Ar throughput ,
+.Ar reliability ,
+or as either hex or decimal.
 .It Ar random-id
 Replaces the IP identification field with random values to compensate
 for predictable values generated by many hosts.
@@ -725,7 +766,7 @@ much in the same way as
 works in the packet filter (see below).
 This mechanism should be used when it is necessary to exclude specific packets
 from broader scrub rules.
-.Sh QUEUEING/ALTQ
+.Sh QUEUEING
 The ALTQ system is currently not available in the GENERIC kernel nor as
 loadable modules.
 In order to use the herein after called queueing options one has to use a
@@ -816,7 +857,7 @@ assigned.
 .Ar Priority
 mainly controls the time packets take to get sent out, while
 .Ar bandwidth
-has primarily effects on throughput.
+primarily affects throughput.
 .Ar hfsc
 supports both link-sharing and guaranteed real-time services.
 It employs a service curve based QoS model,
@@ -879,7 +920,7 @@ Defines a list of subqueues to create on an interface.
 .El
 .Pp
 In the following example, the interface dc0
-should queue up to 5 Mbit/s in four second-level queues using
+should queue up to 5Mbps in four second-level queues using
 Class Based Queueing.
 Those four queues will be shown in a later example.
 .Bd -literal -offset indent
@@ -1171,7 +1212,7 @@ or to the firewall itself.
 Note that redirecting external incoming connections to the loopback
 address, as in
 .Bd -literal -offset indent
-rdr on ne3 inet proto tcp to port spamd -\*(Gt 127.0.0.1 port smtp
+rdr on ne3 inet proto tcp to port smtp -\*(Gt 127.0.0.1 port spamd
 .Ed
 .Pp
 will effectively allow an external host to connect to daemons
@@ -1256,7 +1297,7 @@ block all
 .Ed
 .It Ar pass
 The packet is passed;
-state is created state unless the
+state is created unless the
 .Ar no state
 option is specified.
 .El
@@ -1432,7 +1473,8 @@ This rule applies only to packets with the specified source and destination
 addresses and ports.
 .Pp
 Addresses can be specified in CIDR notation (matching netblocks), as
-symbolic host names or interface names, or as any of the following keywords:
+symbolic host names, interface names or interface group names, or as any
+of the following keywords:
 .Pp
 .Bl -tag -width xxxxxxxxxxxxxx -compact
 .It Ar any
@@ -1454,7 +1496,15 @@ the route back to the packet's source address.
 Any address that matches the given table.
 .El
 .Pp
-Interface names can have modifiers appended:
+Ranges of addresses are specified by using the
+.Sq -
+operator.
+For instance:
+.Dq 10.1.1.10 - 10.1.1.12
+means all addresses from 10.1.1.10 to 10.1.1.12,
+hence addresses 10.1.1.10, 10.1.1.11, and 10.1.1.12.
+.Pp
+Interface names and interface group names can have modifiers appended:
 .Pp
 .Bl -tag -width xxxxxxxxxxxx -compact
 .It Ar :network
@@ -1462,7 +1512,7 @@ Translates to the network(s) attached to the interface.
 .It Ar :broadcast
 Translates to the interface's broadcast address(es).
 .It Ar :peer
-Translates to the point to point interface's peer address(es).
+Translates to the point-to-point interface's peer address(es).
 .It Ar :0
 Do not include interface aliases.
 .El
@@ -1552,17 +1602,6 @@ This is equivalent to "from any to any".
 Similar to
 .Ar user ,
 this rule only applies to packets of sockets owned by the specified group.
-.Pp
-The use of
-.Ar group
-or
-.Ar user
-in
-.Va debug.mpsafenet Ns = Ns 1
-environments may result in a deadlock.
-Please see the
-.Sx BUGS
-section for details.
 .It Ar user Aq Ar user
 This rule only applies to packets of sockets owned by the specified user.
 For outgoing connections initiated from the firewall, this is the user
@@ -1628,7 +1667,7 @@ Flags not specified in
 are ignored.
 For stateful connections, the default is
 .Ar flags S/SA .
-To indicate that flags should not be checkd at all, specify
+To indicate that flags should not be checked at all, specify
 .Ar flags any .
 The flags are: (F)IN, (S)YN, (R)ST, (P)USH, (A)CK, (U)RG, (E)CE, and C(W)R.
 .Bl -tag -width Fl
@@ -1780,7 +1819,7 @@ of
 .Em lowdelay
 and TCP ACKs with no data payload will be assigned to the second one.
 See
-.Sx QUEUEING/ALTQ
+.Sx QUEUEING
 for setup details.
 .Pp
 For example:
@@ -1811,7 +1850,8 @@ or
 rules in addition to filter rules.
 Tags take the same macros as labels (see above).
 .It Ar tagged Aq Ar string
-Used with filter or translation rules to specify that packets must already
+Used with filter, translation or scrub rules
+to specify that packets must already
 be tagged with the given tag in order to match the rule.
 Inverse tag matching can also be done
 by specifying the
@@ -1822,6 +1862,22 @@ keyword.
 .It Ar rtable Aq Ar number
 Used to select an alternate routing table for the routing lookup.
 Only effective before the route lookup happened, i.e. when filtering inbound.
+.It Xo Ar divert-to Aq Ar host
+.Ar port Aq Ar port
+.Xc
+Used to redirect packets to a local socket bound to
+.Ar host
+and
+.Ar port .
+The packets will not be modified, so
+.Xr getsockname 2
+on the socket will return the original destination address of the packet.
+.It Ar divert-reply
+Used to receive replies for sockets that are bound to addresses
+which are not local to the machine.
+See
+.Xr setsockopt 2
+for information on how to bind these sockets.
 .It Ar probability Aq Ar number
 A probability attribute can be attached to a rule, with a value set between
 0 and 1, bounds not included.
@@ -1940,7 +1996,7 @@ pool options.
 Note that by default these associations are destroyed as soon as there are
 no longer states which refer to them; in order to make the mappings last
 beyond the lifetime of the states, increase the global options with
-.Ar set timeout source-track
+.Ar set timeout src.track .
 See
 .Sx STATEFUL TRACKING OPTIONS
 for more ways to control the source tracking.
@@ -2026,7 +2082,7 @@ Rules with
 will not work if
 .Xr pf 4
 operates on a
-.Xr if_bridge 4 .
+.Xr bridge 4 .
 .Pp
 Example:
 .Bd -literal -offset indent
@@ -2046,8 +2102,8 @@ must be specified explicitly to apply options to a rule.
 .Bl -tag -width xxxx -compact
 .It Ar max Aq Ar number
 Limits the number of concurrent states the rule may create.
-When this limit is reached, further packets matching the rule that would
-create state are dropped, until existing states time out.
+When this limit is reached, further packets that would create
+state will not match this rule until existing states time out.
 .It Ar no-sync
 Prevent state changes for states created by this rule from appearing on the
 .Xr pfsync 4
@@ -2064,8 +2120,12 @@ Uses a sloppy TCP connection tracker that does not check sequence
 numbers at all, which makes insertion and ICMP teardown attacks way
 easier.
 This is intended to be used in situations where one does not see all
-packets of a connection, i.e. in asymmetric routing situations.
+packets of a connection, e.g. in asymmetric routing situations.
 Cannot be used with modulate or synproxy state.
+.It Ar pflow
+States created by this rule are exported on the
+.Xr pflow 4
+interface.
 .El
 .Pp
 Multiple options can be specified, separated by commas:
@@ -2472,10 +2532,8 @@ into the anchor.
 .Pp
 Optionally,
 .Ar anchor
-rules can specify the parameter's
-direction, interface, address family, protocol and source/destination
-address/port
-using the same syntax as filter rules.
+rules can specify packet filtering parameters using the same syntax as
+filter rules.
 When parameters are used, the
 .Ar anchor
 rule is only evaluated for matching packets.
@@ -2779,10 +2837,11 @@ in BNF:
 .Bd -literal
 line           = ( option | pf-rule | nat-rule | binat-rule | rdr-rule |
                  antispoof-rule | altq-rule | queue-rule | trans-anchors |
-		 anchor-rule | anchor-close | load-anchor | table-rule | )
+                 anchor-rule | anchor-close | load-anchor | table-rule |
+                 include )
 
 option         = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
-		 [ "ruleset-optimization" [ "none" | "basic" | "profile" ]] |
+                 [ "ruleset-optimization" [ "none" | "basic" | "profile" ]] |
                  [ "optimization" [ "default" | "normal" |
                  "high-latency" | "satellite" |
                  "aggressive" | "conservative" ] ]
@@ -2790,9 +2849,10 @@ option         = "set" ( [ "timeout" ( timeout | "{" timeout-list "}" ) ] |
                  [ "loginterface" ( interface-name | "none" ) ] |
                  [ "block-policy" ( "drop" | "return" ) ] |
                  [ "state-policy" ( "if-bound" | "floating" ) ]
+                 [ "state-defaults" state-opts ]
                  [ "require-order" ( "yes" | "no" ) ]
                  [ "fingerprints" filename ] |
-                 [ "skip on" ( interface-name | "{" interface-list "}" ) ] |
+                 [ "skip on" ifspec ] |
                  [ "debug" ( "none" | "urgent" | "misc" | "loud" ) ] )
 
 pf-rule        = action [ ( "in" | "out" ) ]
@@ -2804,10 +2864,10 @@ logopts        = logopt [ "," logopts ]
 logopt         = "all" | "user" | "to" interface-name
 
 filteropt-list = filteropt-list filteropt | filteropt
-filteropt      = user | group | flags | icmp-type | icmp6-type | tos |
+filteropt      = user | group | flags | icmp-type | icmp6-type | "tos" tos |
                  ( "no" | "keep" | "modulate" | "synproxy" ) "state"
                  [ "(" state-opts ")" ] |
-                 "fragment" | "no-df" | "min-ttl" number |
+                 "fragment" | "no-df" | "min-ttl" number | "set-tos" tos |
                  "max-mss" number | "random-id" | "reassemble tcp" |
                  fragmentation | "allow-opts" |
                  "label" string | "tag" string | [ ! ] "tagged" string |
@@ -2834,17 +2894,16 @@ rdr-rule       = [ "no" ] "rdr" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
                  [ portspec ] [ pooltype ] ]
 
 antispoof-rule = "antispoof" [ "log" ] [ "quick" ]
-                 "for" ( interface-name | "{" interface-list "}" )
-                 [ af ] [ "label" string ]
+                 "for" ifspec [ af ] [ "label" string ]
 
 table-rule     = "table" "\*(Lt" string "\*(Gt" [ tableopts-list ]
 tableopts-list = tableopts-list tableopts | tableopts
-tableopts      = "persist" | "const" | "file" string |
+tableopts      = "persist" | "const" | "counters" | "file" string |
                  "{" [ tableaddr-list ] "}"
 tableaddr-list = tableaddr-list [ "," ] tableaddr-spec | tableaddr-spec
 tableaddr-spec = [ "!" ] tableaddr [ "/" mask-bits ]
-tableaddr      = hostname | ipv4-dotted-quad | ipv6-coloned-hex |
-                 interface-name | "self"
+tableaddr      = hostname | ifspec | "self" |
+                 ipv4-dotted-quad | ipv6-coloned-hex
 
 altq-rule      = "altq on" interface-name queueopts-list
                  "queue" subqueue
@@ -2852,7 +2911,7 @@ queue-rule     = "queue" string [ "on" interface-name ] queueopts-list
                  subqueue
 
 anchor-rule    = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ]
-                 [ af ] [ protospec ] [ hosts ] [ "{" ]
+                 [ af ] [ protospec ] [ hosts ] [ filteropt-list ] [ "{" ]
 
 anchor-close   = "}"
 
@@ -2875,8 +2934,10 @@ return         = "drop" | "return" | "return-rst" [ "( ttl" number ")" ] |
 icmpcode       = ( icmp-code-name | icmp-code-number )
 icmp6code      = ( icmp6-code-name | icmp6-code-number )
 
-ifspec         = ( [ "!" ] interface-name ) | "{" interface-list "}"
-interface-list = [ "!" ] interface-name [ [ "," ] interface-list ]
+ifspec         = ( [ "!" ] ( interface-name | interface-group ) ) |
+                 "{" interface-list "}"
+interface-list = [ "!" ] ( interface-name | interface-group )
+                 [ [ "," ] interface-list ]
 route          = ( "route-to" | "reply-to" | "dup-to" )
                  ( routehost | "{" routehost-list "}" )
                  [ pooltype ]
@@ -2896,8 +2957,9 @@ ipspec         = "any" | host | "{" host-list "}"
 host           = [ "!" ] ( address [ "/" mask-bits ] | "\*(Lt" string "\*(Gt" )
 redirhost      = address [ "/" mask-bits ]
 routehost      = "(" interface-name [ address [ "/" mask-bits ] ] ")"
-address        = ( interface-name | "(" interface-name ")" | hostname |
-                 ipv4-dotted-quad | ipv6-coloned-hex )
+address        = ( interface-name | interface-group |
+                 "(" ( interface-name | interface-group ) ")" |
+                 hostname | ipv4-dotted-quad | ipv6-coloned-hex )
 host-list      = host [ [ "," ] host-list ]
 redirhost-list = redirhost [ [ "," ] redirhost-list ]
 routehost-list = routehost [ [ "," ] routehost-list ]
@@ -2926,11 +2988,11 @@ icmp-type-code = ( icmp-type-name | icmp-type-number )
                  [ "code" ( icmp-code-name | icmp-code-number ) ]
 icmp-list      = icmp-type-code [ [ "," ] icmp-list ]
 
-tos            = "tos" ( "lowdelay" | "throughput" | "reliability" |
+tos            = ( "lowdelay" | "throughput" | "reliability" |
                  [ "0x" ] number )
 
 state-opts     = state-opt [ [ "," ] state-opts ]
-state-opt      = ( "max" number | "no-sync" | timeout | sloppy |
+state-opt      = ( "max" number | "no-sync" | timeout | "sloppy" | "pflow" |
                  "source-track" [ ( "rule" | "global" ) ] |
                  "max-src-nodes" number | "max-src-states" number |
                  "max-src-conn" number |
@@ -2971,9 +3033,10 @@ realtime-sc    = "realtime" sc-spec
 upperlimit-sc  = "upperlimit" sc-spec
 sc-spec        = ( bandwidth-spec |
                  "(" bandwidth-spec number bandwidth-spec ")" )
+include        = "include" filename
 .Ed
 .Sh FILES
-.Bl -tag -width "/usr/share/examples/pf" -compact
+.Bl -tag -width "/etc/protocols" -compact
 .It Pa /etc/hosts
 Host name database.
 .It Pa /etc/pf.conf
@@ -2984,8 +3047,6 @@ Default location of OS fingerprints.
 Protocol name database.
 .It Pa /etc/services
 Service name database.
-.It Pa /usr/share/examples/pf
-Example rulesets.
 .El
 .Sh BUGS
 Due to a lock order reversal (LOR) with the socket layer, the use of the
@@ -3017,6 +3078,7 @@ Rules with a route label do not match any traffic.
 .Xr ip 4 ,
 .Xr ip6 4 ,
 .Xr pf 4 ,
+.Xr pflow 4 ,
 .Xr pfsync 4 ,
 .Xr route 4 ,
 .Xr tcp 4 ,
diff --git a/contrib/pf/man/pf.os.5 b/contrib/pf/man/pf.os.5
index ac2b7a8..5930525 100644
--- a/contrib/pf/man/pf.os.5
+++ b/contrib/pf/man/pf.os.5
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: pf.os.5,v 1.7 2005/11/16 20:07:18 stevesk Exp $
+.\"	$OpenBSD: pf.os.5,v 1.8 2007/05/31 19:19:58 jmc Exp $
 .\"
 .\" Copyright (c) 2003 Mike Frantzen 
 .\"
@@ -16,7 +16,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 18, 2003
+.Dd May 31 2007
 .Dt PF.OS 5
 .Os
 .Sh NAME
@@ -217,7 +217,7 @@ almost translates into the following fingerprint
   57344:64:1:44:M1460:	exampleOS:1.0::exampleOS 1.0
 .Ed
 .Sh SEE ALSO
-.Xr tcpdump 1 ,
 .Xr pf 4 ,
 .Xr pf.conf 5 ,
-.Xr pfctl 8
+.Xr pfctl 8 ,
+.Xr tcpdump 1
diff --git a/contrib/pf/man/pflog.4 b/contrib/pf/man/pflog.4
index 7ab96e9..c1039a3 100644
--- a/contrib/pf/man/pflog.4
+++ b/contrib/pf/man/pflog.4
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: pflog.4,v 1.9 2006/10/25 12:51:31 jmc Exp $
+.\"	$OpenBSD: pflog.4,v 1.10 2007/05/31 19:19:51 jmc Exp $
 .\"
 .\" Copyright (c) 2001 Tobias Weingartner
 .\" All rights reserved.
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 10, 2001
+.Dd May 31 2007
 .Dt PFLOG 4
 .Os
 .Sh NAME
@@ -36,7 +36,7 @@
 .Sh DESCRIPTION
 The
 .Nm pflog
-interface is a pseudo-device which makes visible all packets logged by
+interface is a device which makes visible all packets logged by
 the packet filter,
 .Xr pf 4 .
 Logged packets can easily be monitored in real
@@ -91,13 +91,13 @@ and monitor all packets logged on it:
 # tcpdump -n -e -ttt -i pflog1
 .Ed
 .Sh SEE ALSO
-.Xr tcpdump 1
 .Xr inet 4 ,
 .Xr inet6 4 ,
 .Xr netintro 4 ,
 .Xr pf 4 ,
 .Xr ifconfig 8 ,
-.Xr pflogd 8
+.Xr pflogd 8 ,
+.Xr tcpdump 1
 .Sh HISTORY
 The
 .Nm
diff --git a/contrib/pf/man/pfsync.4 b/contrib/pf/man/pfsync.4
index 63adca9..92534f7 100644
--- a/contrib/pf/man/pfsync.4
+++ b/contrib/pf/man/pfsync.4
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: pfsync.4,v 1.24 2006/10/23 07:05:49 jmc Exp $
+.\"	$OpenBSD: pfsync.4,v 1.28 2009/02/17 10:05:18 dlg Exp $
 .\"
 .\" Copyright (c) 2002 Michael Shalayeff
 .\" Copyright (c) 2003-2004 Ryan McBride
@@ -26,12 +26,12 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 6, 2006
+.Dd February 17 2009
 .Dt PFSYNC 4
 .Os
 .Sh NAME
 .Nm pfsync
-.Nd packet filter state table logging interface
+.Nd packet filter state table sychronisation interface
 .Sh SYNOPSIS
 .Cd "device pfsync"
 .Sh DESCRIPTION
@@ -40,26 +40,25 @@ The
 interface is a pseudo-device which exposes certain changes to the state
 table used by
 .Xr pf 4 .
-.\" XXX: not yet!
-.\" State changes can be viewed by invoking
-.\" .Xr tcpdump 1
-.\" on the
-.\" .Nm
-.\" interface.
+State changes can be viewed by invoking
+.Xr tcpdump 1
+on the
+.Nm
+interface.
 If configured with a physical synchronisation interface,
 .Nm
-will send state changes out on that interface using IP multicast,
+will also send state changes out on that interface,
 and insert state changes received on that interface from other systems
 into the state table.
 .Pp
 By default, all local changes to the state table are exposed via
 .Nm .
-However, state changes from packets received by
+State changes from packets received by
 .Nm
 over the network are not rebroadcast.
-States created by a rule marked with the
+Updates to states created by a rule marked with the
 .Ar no-sync
-keyword are omitted from the
+keyword are ignored by the
 .Nm
 interface (see
 .Xr pf.conf 5
@@ -67,33 +66,19 @@ for details).
 .Pp
 The
 .Nm
-interface will attempt to collapse multiple updates of the same
-state into one message where possible.
-The maximum number of times this can be done before the update is sent out
-is controlled by the
+interface will attempt to collapse multiple state updates into a single
+packet where possible.
+The maximum number of times a single state can be updated before a
+.Nm
+packet will be sent out is controlled by the
 .Ar maxupd
 parameter to ifconfig
 (see
 .Xr ifconfig 8
 and the example below for more details).
-.Pp
-Each packet retrieved on this interface has a header associated
-with it of length
-.Dv PFSYNC_HDRLEN .
-The header indicates the version of the protocol, address family,
-action taken on the following states, and the number of state
-table entries attached in this packet.
-This structure is defined in
-.Aq Pa net/if_pfsync.h
-as:
-.Bd -literal -offset indent
-struct pfsync_header {
-	u_int8_t version;
-	u_int8_t af;
-	u_int8_t action;
-	u_int8_t count;
-};
-.Ed
+The sending out of a
+.Nm
+packet will be delayed by a maximum of one second.
 .Sh NETWORK SYNCHRONISATION
 States can be synchronised between two or more firewalls using this
 interface, by specifying a synchronisation interface using
@@ -104,18 +89,16 @@ interface:
 # ifconfig pfsync0 syncdev fxp0
 .Ed
 .Pp
-It is important that the underlying synchronisation interface is up
-and has an IP address assigned.
-.Pp
 By default, state change messages are sent out on the synchronisation
-interface using IP multicast packets.
-The protocol is IP protocol 240, PFSYNC, and the multicast group
-used is 224.0.0.240.
-When a peer address is specified using the
+interface using IP multicast packets to the 244.0.0.240 group address.
+An alternative destination address for
+.Nm
+packets can be specified using the
 .Ic syncpeer
-keyword, the peer address is used as a destination for the pfsync traffic,
-and the traffic can then be protected using
-.Xr ipsec 4 .
+keyword.
+This can be used in combination with
+.Xr ipsec 4
+to protect the synchronisation traffic.
 In such a configuration, the syncdev should be set to the
 .Xr enc 4
 interface, as this is where the traffic arrives when it is decapsulated,
@@ -127,50 +110,19 @@ e.g.:
 It is important that the pfsync traffic be well secured
 as there is no authentication on the protocol and it would
 be trivial to spoof packets which create states, bypassing the pf ruleset.
-Either run the pfsync protocol on a trusted network \- ideally  a network
+Either run the pfsync protocol on a trusted network \- ideally a network
 dedicated to pfsync messages such as a crossover cable between two firewalls,
 or specify a peer address and protect the traffic with
 .Xr ipsec 4 .
-.Pp
-For
-.Nm
-to start its operation automatically at the system boot time,
-.Va pfsync_enable
-and
-.Va pfsync_syncdev
-variables should be used in
-.Xr rc.conf 5 .
-It is not advisable to set up
-.Nm
-with common network interface configuration variables of
-.Xr rc.conf 5
-because
-.Nm
-must start after its
-.Cm syncdev ,
-which cannot be always ensured in the latter case.
-.\" XXX: not yet!
-.\" .Pp
-.\" There is a one-to-one correspondence between packets seen by
-.\" .Xr bpf 4
-.\" on the
-.\" .Nm
-.\" interface, and packets sent out on the synchronisation interface, i.e.\&
-.\" a packet with 4 state deletion messages on
-.\" .Nm
-.\" means that the same 4 deletions were sent out on the synchronisation
-.\" interface.
-.\" However, the actual packet contents may differ as the messages
-.\" sent over the network are "compressed" where possible, containing
-.\" only the necessary information.
 .Sh EXAMPLES
 .Nm
 and
 .Xr carp 4
 can be used together to provide automatic failover of a pair of firewalls
 configured in parallel.
-One firewall handles all traffic \- if it dies or
-is shut down, the second firewall takes over automatically.
+One firewall will handle all traffic until it dies, is shut down, or is
+manually demoted, at which point the second firewall will take over
+automatically.
 .Pp
 Both firewalls in this example have three
 .Xr sis 4
@@ -208,12 +160,12 @@ traffic through.
 The following should be added to the top of
 .Pa /etc/pf.conf :
 .Bd -literal -offset indent
-pass quick on { sis2 } proto pfsync
-pass on { sis0 sis1 } proto carp
+pass quick on { sis2 } proto pfsync keep state (no-sync)
+pass on { sis0 sis1 } proto carp keep state (no-sync)
 .Ed
 .Pp
-If it is preferable that one firewall handle the traffic,
-the
+It is preferable that one firewall handle the forwarding of all the traffic,
+therefore the
 .Ar advskew
 on the backup firewall's
 .Xr carp 4
@@ -221,6 +173,7 @@ interfaces should be set to something higher than
 the primary's.
 For example, if firewall B is the backup, its
 carp1 configuration would look like this:
+would look like this:
 .Bd -literal -offset indent
 ifconfig_carp1="vhid 2 pass bar advskew 100 192.168.0.1/24"
 .Ed
@@ -230,16 +183,10 @@ The following must also be added to
 .Bd -literal -offset indent
 net.inet.carp.preempt=1
 .Ed
-.Sh BUGS
-Possibility to view state changes using
-.Xr tcpdump 1
-has not been ported from
-.Ox
-yet.
 .Sh SEE ALSO
 .Xr bpf 4 ,
 .Xr carp 4 ,
-.Xr ifconfig 8 ,
+.Xr enc 4 ,
 .Xr inet 4 ,
 .Xr inet6 4 ,
 .Xr ipsec 4 ,
@@ -247,16 +194,20 @@ yet.
 .Xr pf 4 ,
 .Xr pf.conf 5 ,
 .Xr protocols 5 ,
-.Xr rc.conf 5
+.Xr rc.conf 5 ,
 .Xr ifconfig 8 ,
 .Xr ifstated 8 ,
-.Xr tcpdump 8
+.Xr tcpdump 1
 .Sh HISTORY
 The
 .Nm
 device first appeared in
 .Ox 3.3 .
+.Pp
 The
 .Nm
-device was imported to
-.Fx 5.3 .
+protocol and kernel implementation were significantly modified between
+.Ox 4.4
+and
+.Ox 4.5 .
+The two protocols are incompatible and will not interoperate.
diff --git a/contrib/pf/pfctl/parse.y b/contrib/pf/pfctl/parse.y
index c22a0b6..440692e 100644
--- a/contrib/pf/pfctl/parse.y
+++ b/contrib/pf/pfctl/parse.y
@@ -1,4 +1,4 @@
-/*	$OpenBSD: parse.y,v 1.517 2007/02/03 23:26:40 dhartmei Exp $	*/
+/*	$OpenBSD: parse.y,v 1.554 2008/10/17 12:59:53 henning Exp $	*/
 
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -62,15 +64,8 @@ __FBSDID("$FreeBSD$");
 #include "pfctl_parser.h"
 #include "pfctl.h"
 
-#ifdef __FreeBSD__
-#define	HTONL(x)	(x) = htonl((__uint32_t)(x))
-#endif
-
 static struct pfctl	*pf = NULL;
-static FILE		*fin = NULL;
 static int		 debug = 0;
-static int		 lineno = 1;
-static int		 errors = 0;
 static int		 rulestate = 0;
 static u_int16_t	 returnicmpdefault =
 			    (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
@@ -80,6 +75,39 @@ static int		 blockpolicy = PFRULE_DROP;
 static int		 require_order = 1;
 static int		 default_statelock;
 
+TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
+static struct file {
+	TAILQ_ENTRY(file)	 entry;
+	FILE			*stream;
+	char			*name;
+	int			 lineno;
+	int			 errors;
+} *file;
+struct file	*pushfile(const char *, int);
+int		 popfile(void);
+int		 check_file_secrecy(int, const char *);
+int		 yyparse(void);
+int		 yylex(void);
+int		 yyerror(const char *, ...);
+int		 kw_cmp(const void *, const void *);
+int		 lookup(char *);
+int		 lgetc(int);
+int		 lungetc(int);
+int		 findeol(void);
+
+TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
+struct sym {
+	TAILQ_ENTRY(sym)	 entry;
+	int			 used;
+	int			 persist;
+	char			*nam;
+	char			*val;
+};
+int		 symset(const char *, const char *, int);
+char		*symget(const char *);
+
+int		 atoul(char *, u_long *);
+
 enum {
 	PFCTL_STATE_NONE,
 	PFCTL_STATE_OPTION,
@@ -128,7 +156,8 @@ enum	{ PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
 	    PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
 	    PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
 	    PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
-	    PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY };
+	    PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, 
+	    PF_STATE_OPT_PFLOW };
 
 enum	{ PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
 
@@ -206,26 +235,34 @@ struct filter_opts {
 	char			*tag;
 	char			*match_tag;
 	u_int8_t		 match_tag_not;
-	int			 rtableid;
+	u_int			 rtableid;
+	struct {
+		struct node_host	*addr;
+		u_int16_t		port;
+	}			 divert;
 } filter_opts;
 
 struct antispoof_opts {
 	char			*label;
-	int			 rtableid;
+	u_int			 rtableid;
 } antispoof_opts;
 
 struct scrub_opts {
-	int			marker;
+	int			 marker;
 #define SOM_MINTTL	0x01
 #define SOM_MAXMSS	0x02
 #define SOM_FRAGCACHE	0x04
-	int			nodf;
-	int			minttl;
-	int			maxmss;
-	int			fragcache;
-	int			randomid;
-	int			reassemble_tcp;
-	int			rtableid;
+#define SOM_SETTOS	0x08
+	int			 nodf;
+	int			 minttl;
+	int			 maxmss;
+	int			 settos;
+	int			 fragcache;
+	int			 randomid;
+	int			 reassemble_tcp;
+	char			*match_tag;
+	u_int8_t		 match_tag_not;
+	u_int			 rtableid;
 } scrub_opts;
 
 struct queue_opts {
@@ -260,63 +297,45 @@ struct pool_opts {
 } pool_opts;
 
 
-struct node_hfsc_opts	hfsc_opts;
-
-int	yyerror(const char *, ...);
-int	disallow_table(struct node_host *, const char *);
-int	disallow_urpf_failed(struct node_host *, const char *);
-int	disallow_alias(struct node_host *, const char *);
-int	rule_consistent(struct pf_rule *, int);
-int	filter_consistent(struct pf_rule *, int);
-int	nat_consistent(struct pf_rule *);
-int	rdr_consistent(struct pf_rule *);
-int	process_tabledef(char *, struct table_opts *);
-int	yyparse(void);
-void	expand_label_str(char *, size_t, const char *, const char *);
-void	expand_label_if(const char *, char *, size_t, const char *);
-void	expand_label_addr(const char *, char *, size_t, u_int8_t,
-	    struct node_host *);
-void	expand_label_port(const char *, char *, size_t, struct node_port *);
-void	expand_label_proto(const char *, char *, size_t, u_int8_t);
-void	expand_label_nr(const char *, char *, size_t);
-void	expand_label(char *, size_t, const char *, u_int8_t, struct node_host *,
-	    struct node_port *, struct node_host *, struct node_port *,
-	    u_int8_t);
-void	expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
-	    struct node_proto *, struct node_os*, struct node_host *,
-	    struct node_port *, struct node_host *, struct node_port *,
-	    struct node_uid *, struct node_gid *, struct node_icmp *,
-	    const char *);
-int	expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
-	    struct node_queue_bw bwspec, struct node_queue_opt *);
-int	expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
-	    struct node_queue_bw, struct node_queue_opt *);
-int	expand_skip_interface(struct node_if *);
+struct node_hfsc_opts	 hfsc_opts;
+struct node_state_opt	*keep_state_defaults = NULL;
+
+int		 disallow_table(struct node_host *, const char *);
+int		 disallow_urpf_failed(struct node_host *, const char *);
+int		 disallow_alias(struct node_host *, const char *);
+int		 rule_consistent(struct pf_rule *, int);
+int		 filter_consistent(struct pf_rule *, int);
+int		 nat_consistent(struct pf_rule *);
+int		 rdr_consistent(struct pf_rule *);
+int		 process_tabledef(char *, struct table_opts *);
+void		 expand_label_str(char *, size_t, const char *, const char *);
+void		 expand_label_if(const char *, char *, size_t, const char *);
+void		 expand_label_addr(const char *, char *, size_t, u_int8_t,
+		    struct node_host *);
+void		 expand_label_port(const char *, char *, size_t,
+		    struct node_port *);
+void		 expand_label_proto(const char *, char *, size_t, u_int8_t);
+void		 expand_label_nr(const char *, char *, size_t);
+void		 expand_label(char *, size_t, const char *, u_int8_t,
+		    struct node_host *, struct node_port *, struct node_host *,
+		    struct node_port *, u_int8_t);
+void		 expand_rule(struct pf_rule *, struct node_if *,
+		    struct node_host *, struct node_proto *, struct node_os *,
+		    struct node_host *, struct node_port *, struct node_host *,
+		    struct node_port *, struct node_uid *, struct node_gid *,
+		    struct node_icmp *, const char *);
+int		 expand_altq(struct pf_altq *, struct node_if *,
+		    struct node_queue *, struct node_queue_bw bwspec,
+		    struct node_queue_opt *);
+int		 expand_queue(struct pf_altq *, struct node_if *,
+		    struct node_queue *, struct node_queue_bw,
+		    struct node_queue_opt *);
+int		 expand_skip_interface(struct node_if *);
 
 int	 check_rulestate(int);
-int	 kw_cmp(const void *, const void *);
-int	 lookup(char *);
-int	 lgetc(FILE *);
-int	 lungetc(int);
-int	 findeol(void);
-int	 yylex(void);
-int	 atoul(char *, u_long *);
 int	 getservice(char *);
 int	 rule_label(struct pf_rule *, char *);
 
-TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
-struct sym {
-	TAILQ_ENTRY(sym)	 entries;
-	int			 used;
-	int			 persist;
-	char			*nam;
-	char			*val;
-};
-
-
-int	 symset(const char *, const char *, int);
-char	*symget(const char *);
-
 void	 mv_rules(struct pf_ruleset *, struct pf_ruleset *);
 void	 decide_address_family(struct node_host *, sa_family_t *);
 void	 remove_invalid_hosts(struct node_host **, sa_family_t *);
@@ -334,10 +353,11 @@ struct loadanchors {
 
 typedef struct {
 	union {
-		u_int32_t		 number;
+		int64_t			 number;
+		double			 probability;
 		int			 i;
 		char			*string;
-		int			 rtableid;
+		u_int			 rtableid;
 		struct {
 			u_int8_t	 b1;
 			u_int8_t	 b2;
@@ -403,6 +423,10 @@ typedef struct {
 	int lineno;
 } YYSTYPE;
 
+#define PPORT_RANGE	1
+#define PPORT_STAR	2
+int	parseport(char *, struct range *r, int);
+
 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
 	(!((addr).iflags & PFI_AFLAG_NOALIAS) ||		 \
 	!isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
@@ -417,32 +441,37 @@ typedef struct {
 %token	REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
 %token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
 %token	REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
-%token	ANTISPOOF FOR
+%token	ANTISPOOF FOR INCLUDE
 %token	BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
 %token	ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
 %token	QUEUE PRIORITY QLIMIT RTABLE
 %token	LOAD RULESET_OPTIMIZATION
 %token	STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
-%token	MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY
-%token	TAGGED TAG IFBOUND FLOATING STATEPOLICY ROUTE
+%token	MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW
+%token	TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
+%token	DIVERTTO DIVERTREPLY
 %token			STRING
+%token			NUMBER
 %token				PORTBINARY
 %type			interface if_list if_item_not if_item
 %type			number icmptype icmp6type uid gid
 %type			tos not yesno
+%type			probability
 %type				no dir af fragcache optimizer
 %type				sourcetrack flush unaryop statelock
-%type				action nataction natpass scrubaction
+%type				action nataction natpasslog scrubaction
 %type				flags flag blockspec
-%type			port rport
+%type			portplain portstar portrange
 %type			hashkey
 %type			proto proto_list proto_item
+%type			protoval
 %type			icmpspec
 %type			icmp_list icmp_item
 %type			icmp6_list icmp6_item
+%type			reticmpspec reticmp6spec
 %type			fromto
 %type			ipportspec from to
-%type			ipspec xhost host dynaddr host_list
+%type			ipspec toipspec xhost host dynaddr host_list
 %type			redir_host_list redirspec
 %type			route_host route_host_list routespec
 %type				os xos os_list
@@ -451,7 +480,8 @@ typedef struct {
 %type				gids gid_list gid_item
 %type			route
 %type			redirection redirpool
-%type			label string tag anchorname
+%type			label stringall tag anchorname
+%type			string varstring numberstring
 %type			keep
 %type			state_opt_spec state_opt_list state_opt_item
 %type			logquick quick log logopts logopt
@@ -474,6 +504,7 @@ typedef struct {
 %%
 
 ruleset		: /* empty */
+		| ruleset include '\n'
 		| ruleset '\n'
 		| ruleset option '\n'
 		| ruleset scrubrule '\n'
@@ -488,7 +519,22 @@ ruleset		: /* empty */
 		| ruleset antispoof '\n'
 		| ruleset tabledef '\n'
 		| '{' fakeanchor '}' '\n';
-		| ruleset error '\n'		{ errors++; }
+		| ruleset error '\n'		{ file->errors++; }
+		;
+
+include		: INCLUDE STRING		{
+			struct file	*nfile;
+
+			if ((nfile = pushfile($2, 0)) == NULL) {
+				yyerror("failed to include file %s", $2);
+				free($2);
+				YYERROR;
+			}
+			free($2);
+
+			file = nfile;
+			lungetc('\n');
+		}
 		;
 
 /*
@@ -511,7 +557,7 @@ optimizer	: string	{
 			else if (!strcmp($1, "profile"))
 				$$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
 			else {
-				yyerror("unknown ruleset-optimization %s", $$);
+				yyerror("unknown ruleset-optimization %s", $1);
 				YYERROR;
 			}
 		}
@@ -536,10 +582,10 @@ option		: SET OPTIMIZATION STRING		{
 			}
 		}
 		| SET TIMEOUT timeout_spec
-		| SET TIMEOUT '{' timeout_list '}'
+		| SET TIMEOUT '{' optnl timeout_list '}'
 		| SET LIMIT limit_spec
-		| SET LIMIT '{' limit_list '}'
-		| SET LOGINTERFACE STRING		{
+		| SET LIMIT '{' optnl limit_list '}'
+		| SET LOGINTERFACE stringall		{
 			if (check_rulestate(PFCTL_STATE_OPTION)) {
 				free($3);
 				YYERROR;
@@ -552,7 +598,7 @@ option		: SET OPTIMIZATION STRING		{
 			free($3);
 		}
 		| SET HOSTID number {
-			if ($3 == 0) {
+			if ($3 == 0 || $3 > UINT_MAX) {
 				yyerror("hostid must be non-zero");
 				YYERROR;
 			}
@@ -629,9 +675,24 @@ option		: SET OPTIMIZATION STRING		{
 				YYERROR;
 			}
 		}
+		| SET STATEDEFAULTS state_opt_list {
+			if (keep_state_defaults != NULL) {
+				yyerror("cannot redefine state-defaults");
+				YYERROR;
+			}
+			keep_state_defaults = $3;
+		}
+		;
+
+stringall	: STRING	{ $$ = $1; }
+		| ALL		{
+			if (($$ = strdup("all")) == NULL) {
+				err(1, "stringall: strdup");
+			}
+		}
 		;
 
-string		: string STRING				{
+string		: STRING string				{
 			if (asprintf(&$$, "%s %s", $1, $2) == -1)
 				err(1, "string: asprintf");
 			free($1);
@@ -640,7 +701,27 @@ string		: string STRING				{
 		| STRING
 		;
 
-varset		: STRING '=' string		{
+varstring	: numberstring varstring 		{
+			if (asprintf(&$$, "%s %s", $1, $2) == -1)
+				err(1, "string: asprintf");
+			free($1);
+			free($2);
+		}
+		| numberstring
+		;
+
+numberstring	: NUMBER				{
+			char	*s;
+			if (asprintf(&s, "%lld", (long long)$1) == -1) {
+				yyerror("string: asprintf");
+				YYERROR;
+			}
+			$$ = s;
+		}
+		| STRING
+		;
+
+varset		: STRING '=' varstring	{
 			if (pf->opts & PF_OPT_VERBOSE)
 				printf("%s = \"%s\"\n", $1, $3);
 			if (symset($1, $3, 0) == -1)
@@ -654,14 +735,10 @@ anchorname	: STRING			{ $$ = $1; }
 		| /* empty */			{ $$ = NULL; }
 		;
 
-optnl		: optnl '\n'
-		|
-		;
-
-pfa_anchorlist	: pfrule optnl
-		| anchorrule optnl
-		| pfa_anchorlist pfrule optnl
-		| pfa_anchorlist anchorrule optnl
+pfa_anchorlist	: /* empty */
+		| pfa_anchorlist '\n'
+		| pfa_anchorlist pfrule '\n'
+		| pfa_anchorlist anchorrule '\n'
 		;
 
 pfa_anchor	: '{'
@@ -694,6 +771,7 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 		    filter_opts pfa_anchor
 		{
 			struct pf_rule	r;
+			struct node_proto	*proto;
 
 			if (check_rulestate(PFCTL_STATE_FILTER)) {
 				if ($2)
@@ -744,6 +822,55 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 			r.prob = $9.prob;
 			r.rtableid = $9.rtableid;
 
+			if ($9.tag)
+				if (strlcpy(r.tagname, $9.tag,
+				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+					yyerror("tag too long, max %u chars",
+					    PF_TAG_NAME_SIZE - 1);
+					YYERROR;
+				}
+			if ($9.match_tag)
+				if (strlcpy(r.match_tagname, $9.match_tag,
+				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+					yyerror("tag too long, max %u chars",
+					    PF_TAG_NAME_SIZE - 1);
+					YYERROR;
+				}
+			r.match_tag_not = $9.match_tag_not;
+			if (rule_label(&r, $9.label))
+				YYERROR;
+			free($9.label);
+			r.flags = $9.flags.b1;
+			r.flagset = $9.flags.b2;
+			if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
+				yyerror("flags always false");
+				YYERROR;
+			}
+			if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
+				for (proto = $7; proto != NULL &&
+				    proto->proto != IPPROTO_TCP;
+				    proto = proto->next)
+					;	/* nothing */
+				if (proto == NULL && $7 != NULL) {
+					if ($9.flags.b1 || $9.flags.b2)
+						yyerror(
+						    "flags only apply to tcp");
+					if ($8.src_os)
+						yyerror(
+						    "OS fingerprinting only "
+						    "applies to tcp");
+					YYERROR;
+				}
+			}
+
+			r.tos = $9.tos;
+
+			if ($9.keep.action) {
+				yyerror("cannot specify state handling "
+				    "on anchors");
+				YYERROR;
+			}
+
 			if ($9.match_tag)
 				if (strlcpy(r.match_tagname, $9.match_tag,
 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
@@ -758,8 +885,8 @@ anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
 
 			expand_rule(&r, $5, NULL, $7, $8.src_os,
 			    $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
-			    0, 0, 0, pf->astack[pf->asd + 1] ?
-			    pf->alast->name : $2);
+			    $9.uid, $9.gid, $9.icmpspec,
+			    pf->astack[pf->asd + 1] ? pf->alast->name : $2);
 			free($2);
 			pf->astack[pf->asd + 1] = NULL;
 		}
@@ -939,8 +1066,20 @@ scrubrule	: scrubaction dir logquick interface af proto fromto scrub_opts
 				r.min_ttl = $8.minttl;
 			if ($8.maxmss)
 				r.max_mss = $8.maxmss;
+			if ($8.marker & SOM_SETTOS) {
+				r.rule_flag |= PFRULE_SET_TOS;
+				r.set_tos = $8.settos;
+			}
 			if ($8.fragcache)
 				r.rule_flag |= $8.fragcache;
+			if ($8.match_tag)
+				if (strlcpy(r.match_tagname, $8.match_tag,
+				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+					yyerror("tag too long, max %u chars",
+					    PF_TAG_NAME_SIZE - 1);
+					YYERROR;
+				}
+			r.match_tag_not = $8.match_tag_not;
 			r.rtableid = $8.rtableid;
 
 			expand_rule(&r, $4, NULL, $6, $7.src_os,
@@ -973,30 +1112,38 @@ scrub_opt	: NODF	{
 			}
 			scrub_opts.nodf = 1;
 		}
-		| MINTTL number {
+		| MINTTL NUMBER {
 			if (scrub_opts.marker & SOM_MINTTL) {
 				yyerror("min-ttl cannot be respecified");
 				YYERROR;
 			}
-			if ($2 > 255) {
+			if ($2 < 0 || $2 > 255) {
 				yyerror("illegal min-ttl value %d", $2);
 				YYERROR;
 			}
 			scrub_opts.marker |= SOM_MINTTL;
 			scrub_opts.minttl = $2;
 		}
-		| MAXMSS number {
+		| MAXMSS NUMBER {
 			if (scrub_opts.marker & SOM_MAXMSS) {
 				yyerror("max-mss cannot be respecified");
 				YYERROR;
 			}
-			if ($2 > 65535) {
+			if ($2 < 0 || $2 > 65535) {
 				yyerror("illegal max-mss value %d", $2);
 				YYERROR;
 			}
 			scrub_opts.marker |= SOM_MAXMSS;
 			scrub_opts.maxmss = $2;
 		}
+		| SETTOS tos {
+			if (scrub_opts.marker & SOM_SETTOS) {
+				yyerror("set-tos cannot be respecified");
+				YYERROR;
+			}
+			scrub_opts.marker |= SOM_SETTOS;
+			scrub_opts.settos = $2;
+		}
 		| fragcache {
 			if (scrub_opts.marker & SOM_FRAGCACHE) {
 				yyerror("fragcache cannot be respecified");
@@ -1026,15 +1173,17 @@ scrub_opt	: NODF	{
 			}
 			scrub_opts.randomid = 1;
 		}
-		| RTABLE number				{
-#ifndef __FreeBSD__
-			if ($2 > RT_TABLEID_MAX || $2 < 0) {
+		| RTABLE NUMBER				{
+			if ($2 < 0 /* || $2 > RT_TABLEID_MAX */) {
 				yyerror("invalid rtable id");
 				YYERROR;
 			}
-#endif
 			scrub_opts.rtableid = $2;
 		}
+		| not TAGGED string			{
+			scrub_opts.match_tag = $3;
+			scrub_opts.match_tag_not = $1;
+		}
 		;
 
 fragcache	: FRAGMENT REASSEMBLE	{ $$ = 0; /* default */ }
@@ -1108,6 +1257,7 @@ antispoof	: ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
 					r.action = PF_DROP;
 					r.direction = PF_IN;
 					r.log = $2.log;
+					r.logif = $2.logif;
 					r.quick = $2.quick;
 					r.af = $4;
 					if (rule_label(&r, $5.label))
@@ -1128,20 +1278,20 @@ antispoof	: ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
 		}
 		;
 
-antispoof_ifspc	: FOR antispoof_if		{ $$ = $2; }
-		| FOR '{' antispoof_iflst '}'	{ $$ = $3; }
+antispoof_ifspc	: FOR antispoof_if			{ $$ = $2; }
+		| FOR '{' optnl antispoof_iflst '}'	{ $$ = $4; }
 		;
 
-antispoof_iflst	: antispoof_if				{ $$ = $1; }
-		| antispoof_iflst comma antispoof_if	{
+antispoof_iflst	: antispoof_if optnl			{ $$ = $1; }
+		| antispoof_iflst comma antispoof_if optnl {
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
 		}
 		;
 
-antispoof_if  : if_item				{ $$ = $1; }
-		| '(' if_item ')'		{
+antispoof_if	: if_item				{ $$ = $1; }
+		| '(' if_item ')'			{
 			$2->dynamic = 1;
 			$$ = $2;
 		}
@@ -1171,13 +1321,11 @@ antispoof_opt	: label	{
 			}
 			antispoof_opts.label = $1;
 		}
-		| RTABLE number				{
-#ifndef __FreeBSD__
-			if ($2 > RT_TABLEID_MAX || $2 < 0) {
+		| RTABLE NUMBER				{
+			if ($2 < 0 /* || $2 > RT_TABLEID_MAX */ ) {
 				yyerror("invalid rtable id");
 				YYERROR;
 			}
-#endif
 			antispoof_opts.rtableid = $2;
 		}
 		;
@@ -1239,6 +1387,8 @@ table_opt	: STRING		{
 				table_opts.flags |= PFR_TFLAG_CONST;
 			else if (!strcmp($1, "persist"))
 				table_opts.flags |= PFR_TFLAG_PERSIST;
+			else if (!strcmp($1, "counters"))
+				table_opts.flags |= PFR_TFLAG_COUNTERS;
 			else {
 				yyerror("invalid table option '%s'", $1);
 				free($1);
@@ -1246,15 +1396,19 @@ table_opt	: STRING		{
 			}
 			free($1);
 		}
-		| '{' '}'		{ table_opts.init_addr = 1; }
-		| '{' host_list '}'	{
+		| '{' optnl '}'		{ table_opts.init_addr = 1; }
+		| '{' optnl host_list '}'	{
 			struct node_host	*n;
 			struct node_tinit	*ti;
 
-			for (n = $2; n != NULL; n = n->next) {
+			for (n = $3; n != NULL; n = n->next) {
 				switch (n->addr.type) {
 				case PF_ADDR_ADDRMASK:
 					continue; /* ok */
+				case PF_ADDR_RANGE:
+					yyerror("address ranges are not "
+					    "permitted inside tables");
+					break;
 				case PF_ADDR_DYNIFTL:
 					yyerror("dynamic addresses are not "
 					    "permitted inside tables");
@@ -1278,7 +1432,7 @@ table_opt	: STRING		{
 			}
 			if (!(ti = calloc(1, sizeof(*ti))))
 				err(1, "table_opt: calloc");
-			ti->host = $2;
+			ti->host = $3;
 			SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
 			    entries);
 			table_opts.init_addr = 1;
@@ -1387,24 +1541,24 @@ queue_opt	: BANDWIDTH bandwidth	{
 			queue_opts.marker |= QOM_BWSPEC;
 			queue_opts.queue_bwspec = $2;
 		}
-		| PRIORITY number	{
+		| PRIORITY NUMBER	{
 			if (queue_opts.marker & QOM_PRIORITY) {
 				yyerror("priority cannot be respecified");
 				YYERROR;
 			}
-			if ($2 > 255) {
+			if ($2 < 0 || $2 > 255) {
 				yyerror("priority out of range: max 255");
 				YYERROR;
 			}
 			queue_opts.marker |= QOM_PRIORITY;
 			queue_opts.priority = $2;
 		}
-		| QLIMIT number	{
+		| QLIMIT NUMBER	{
 			if (queue_opts.marker & QOM_QLIMIT) {
 				yyerror("qlimit cannot be respecified");
 				YYERROR;
 			}
-			if ($2 > 65535) {
+			if ($2 < 0 || $2 > 65535) {
 				yyerror("qlimit out of range: max 65535");
 				YYERROR;
 			}
@@ -1419,12 +1573,12 @@ queue_opt	: BANDWIDTH bandwidth	{
 			queue_opts.marker |= QOM_SCHEDULER;
 			queue_opts.scheduler = $1;
 		}
-		| TBRSIZE number	{
+		| TBRSIZE NUMBER	{
 			if (queue_opts.marker & QOM_TBRSIZE) {
 				yyerror("tbrsize cannot be respecified");
 				YYERROR;
 			}
-			if ($2 > 65535) {
+			if ($2 < 0 || $2 > 65535) {
 				yyerror("tbrsize too big: max 65535");
 				YYERROR;
 			}
@@ -1467,6 +1621,14 @@ bandwidth	: STRING {
 			free($1);
 			$$.bw_absolute = (u_int32_t)bps;
 		}
+		| NUMBER {
+			if ($1 < 0 || $1 > UINT_MAX) {
+				yyerror("bandwidth number too big");
+				YYERROR;
+			}
+			$$.bw_percent = 0;
+			$$.bw_absolute = $1;
+		}
 		;
 
 scheduler	: CBQ				{
@@ -1563,8 +1725,12 @@ hfscopts_item	: LINKSHARE bandwidth				{
 			hfsc_opts.linkshare.m2 = $2;
 			hfsc_opts.linkshare.used = 1;
 		}
-		| LINKSHARE '(' bandwidth comma number comma bandwidth ')'
+		| LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')'
 		    {
+			if ($5 < 0 || $5 > INT_MAX) {
+				yyerror("timing in curve out of range");
+				YYERROR;
+			}
 			if (hfsc_opts.linkshare.used) {
 				yyerror("linkshare already specified");
 				YYERROR;
@@ -1582,8 +1748,12 @@ hfscopts_item	: LINKSHARE bandwidth				{
 			hfsc_opts.realtime.m2 = $2;
 			hfsc_opts.realtime.used = 1;
 		}
-		| REALTIME '(' bandwidth comma number comma bandwidth ')'
+		| REALTIME '(' bandwidth comma NUMBER comma bandwidth ')'
 		    {
+			if ($5 < 0 || $5 > INT_MAX) {
+				yyerror("timing in curve out of range");
+				YYERROR;
+			}
 			if (hfsc_opts.realtime.used) {
 				yyerror("realtime already specified");
 				YYERROR;
@@ -1601,8 +1771,12 @@ hfscopts_item	: LINKSHARE bandwidth				{
 			hfsc_opts.upperlimit.m2 = $2;
 			hfsc_opts.upperlimit.used = 1;
 		}
-		| UPPERLIMIT '(' bandwidth comma number comma bandwidth ')'
+		| UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')'
 		    {
+			if ($5 < 0 || $5 > INT_MAX) {
+				yyerror("timing in curve out of range");
+				YYERROR;
+			}
 			if (hfsc_opts.upperlimit.used) {
 				yyerror("upperlimit already specified");
 				YYERROR;
@@ -1632,11 +1806,11 @@ hfscopts_item	: LINKSHARE bandwidth				{
 
 qassign		: /* empty */		{ $$ = NULL; }
 		| qassign_item		{ $$ = $1; }
-		| '{' qassign_list '}'	{ $$ = $2; }
+		| '{' optnl qassign_list '}'	{ $$ = $3; }
 		;
 
-qassign_list	: qassign_item			{ $$ = $1; }
-		| qassign_list comma qassign_item	{
+qassign_list	: qassign_item optnl		{ $$ = $1; }
+		| qassign_list comma qassign_item optnl	{
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
@@ -1670,6 +1844,7 @@ pfrule		: action dir logquick interface route af proto fromto
 			int			 srctrack = 0;
 			int			 statelock = 0;
 			int			 adaptive = 0;
+			int			 defaults = 0;
 
 			if (check_rulestate(PFCTL_STATE_FILTER))
 				YYERROR;
@@ -1752,13 +1927,16 @@ pfrule		: action dir logquick interface route af proto fromto
 
 			r.tos = $9.tos;
 			r.keep_state = $9.keep.action;
+			o = $9.keep.options;
 
 			/* 'keep state' by default on pass rules. */
 			if (!r.keep_state && !r.action &&
-			    !($9.marker & FOM_KEEP))
+			    !($9.marker & FOM_KEEP)) {
 				r.keep_state = PF_STATE_NORMAL;
+				o = keep_state_defaults;
+				defaults = 1;
+			}
 
-			o = $9.keep.options;
 			while (o) {
 				struct node_state_opt	*p = o;
 
@@ -1899,6 +2077,15 @@ pfrule		: action dir logquick interface route af proto fromto
 					}
 					r.rule_flag |= PFRULE_STATESLOPPY;
 					break;
+				case PF_STATE_OPT_PFLOW:
+					if (r.rule_flag & PFRULE_PFLOW) {
+						yyerror("state pflow "
+						    "option: multiple "
+						    "definitions");
+						YYERROR;
+					}
+					r.rule_flag |= PFRULE_PFLOW;
+					break;
 				case PF_STATE_OPT_TIMEOUT:
 					if (o->data.timeout.number ==
 					    PFTM_ADAPTIVE_START ||
@@ -1916,7 +2103,8 @@ pfrule		: action dir logquick interface route af proto fromto
 					    o->data.timeout.seconds;
 				}
 				o = o->next;
-				free(p);
+				if (!defaults)
+					free(p);
 			}
 
 			/* 'flags S/SA' by default on stateful rules */
@@ -2035,6 +2223,34 @@ pfrule		: action dir logquick interface route af proto fromto
 				}
 				free($9.queues.pqname);
 			}
+#ifdef __FreeBSD__
+			r.divert.port = $9.divert.port;
+#else
+			if ((r.divert.port = $9.divert.port)) {
+				if (r.direction == PF_OUT) {
+					if ($9.divert.addr) {
+						yyerror("address specified "
+						    "for outgoing divert");
+						YYERROR;
+					}
+					bzero(&r.divert.addr,
+					    sizeof(r.divert.addr));
+				} else {
+					if (!$9.divert.addr) {
+						yyerror("no address specified "
+						    "for incoming divert");
+						YYERROR;
+					}
+					if ($9.divert.addr->af != r.af) {
+						yyerror("address family "
+						    "mismatch for divert");
+						YYERROR;
+					}
+					r.divert.addr =
+					    $9.divert.addr->addr.v.a.addr;
+				}
+			}
+#endif
 
 			expand_rule(&r, $4, $5.host, $7, $8.src_os,
 			    $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
@@ -2088,13 +2304,13 @@ filter_opt	: USER uids {
 			filter_opts.marker |= FOM_ICMP;
 			filter_opts.icmpspec = $1;
 		}
-		| tos {
+		| TOS tos {
 			if (filter_opts.marker & FOM_TOS) {
 				yyerror("tos cannot be redefined");
 				YYERROR;
 			}
 			filter_opts.marker |= FOM_TOS;
-			filter_opts.tos = $1;
+			filter_opts.tos = $2;
 		}
 		| keep {
 			if (filter_opts.marker & FOM_KEEP) {
@@ -2132,39 +2348,84 @@ filter_opt	: USER uids {
 			filter_opts.match_tag = $3;
 			filter_opts.match_tag_not = $1;
 		}
-		| PROBABILITY STRING			{
-			char	*e;
-			double	 p = strtod($2, &e);
+		| PROBABILITY probability		{
+			double	p;
 
-			if (*e == '%') {
-				p *= 0.01;
-				e++;
+			p = floor($2 * UINT_MAX + 0.5);
+			if (p < 0.0 || p > UINT_MAX) {
+				yyerror("invalid probability: %lf", p);
+				YYERROR;
 			}
-			if (*e) {
-				yyerror("invalid probability: %s", $2);
-				free($2);
+			filter_opts.prob = (u_int32_t)p;
+			if (filter_opts.prob == 0)
+				filter_opts.prob = 1;
+		}
+		| RTABLE NUMBER				{
+			if ($2 < 0 /* || $2 > RT_TABLEID_MAX */ ) {
+				yyerror("invalid rtable id");
 				YYERROR;
 			}
-			p = floor(p * (UINT_MAX+1.0) + 0.5);
-			if (p < 1.0 || p >= (UINT_MAX+1.0)) {
-				yyerror("invalid probability: %s", $2);
-				free($2);
+			filter_opts.rtableid = $2;
+		}
+		| DIVERTTO portplain {
+#ifdef __FreeBSD__
+			filter_opts.divert.port = $2.a;
+			if (!filter_opts.divert.port) {
+				yyerror("invalid divert port: %u", ntohs($2.a));
 				YYERROR;
 			}
-			filter_opts.prob = (u_int32_t)p;
-			free($2);
+#endif
 		}
-		| RTABLE number				{
+		| DIVERTTO STRING PORT portplain {
 #ifndef __FreeBSD__
-			if ($2 > RT_TABLEID_MAX || $2 < 0) {
-				yyerror("invalid rtable id");
+			if ((filter_opts.divert.addr = host($2)) == NULL) {
+				yyerror("could not parse divert address: %s",
+				    $2);
+				free($2);
 				YYERROR;
 			}
+#else
+			if ($2)
 #endif
-			filter_opts.rtableid = $2;
+			free($2);
+			filter_opts.divert.port = $4.a;
+			if (!filter_opts.divert.port) {
+				yyerror("invalid divert port: %u", ntohs($4.a));
+				YYERROR;
+			}
+		}
+		| DIVERTREPLY {
+#ifdef __FreeBSD__
+			yyerror("divert-reply has no meaning in FreeBSD pf(4)");
+			YYERROR;
+#else
+			filter_opts.divert.port = 1;	/* some random value */
+#endif
+		}
+		;
+
+probability	: STRING				{
+			char	*e;
+			double	 p = strtod($1, &e);
+
+			if (*e == '%') {
+				p *= 0.01;
+				e++;
+			}
+			if (*e) {
+				yyerror("invalid probability: %s", $1);
+				free($1);
+				YYERROR;
+			}
+			free($1);
+			$$ = p;
+		}
+		| NUMBER				{
+			$$ = (double)$1;
 		}
 		;
 
+
 action		: PASS			{ $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
 		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
 		;
@@ -2184,8 +2445,8 @@ blockspec	: /* empty */		{
 			$$.w = 0;
 			$$.w2 = 0;
 		}
-		| RETURNRST '(' TTL number ')'	{
-			if ($4 > 255) {
+		| RETURNRST '(' TTL NUMBER ')'	{
+			if ($4 < 0 || $4 > 255) {
 				yyerror("illegal ttl value %d", $4);
 				YYERROR;
 			}
@@ -2203,34 +2464,20 @@ blockspec	: /* empty */		{
 			$$.w = returnicmpdefault;
 			$$.w2 = returnicmp6default;
 		}
-		| RETURNICMP '(' STRING ')'	{
+		| RETURNICMP '(' reticmpspec ')'	{
 			$$.b2 = PFRULE_RETURNICMP;
-			if (!($$.w = parseicmpspec($3, AF_INET))) {
-				free($3);
-				YYERROR;
-			}
-			free($3);
-			$$.w2 = returnicmp6default;
+			$$.w = $3;
+			$$.w2 = returnicmpdefault;
 		}
-		| RETURNICMP6 '(' STRING ')'	{
+		| RETURNICMP6 '(' reticmp6spec ')'	{
 			$$.b2 = PFRULE_RETURNICMP;
 			$$.w = returnicmpdefault;
-			if (!($$.w2 = parseicmpspec($3, AF_INET6))) {
-				free($3);
-				YYERROR;
-			}
-			free($3);
+			$$.w2 = $3;
 		}
-		| RETURNICMP '(' STRING comma STRING ')' {
+		| RETURNICMP '(' reticmpspec comma reticmp6spec ')' {
 			$$.b2 = PFRULE_RETURNICMP;
-			if (!($$.w = parseicmpspec($3, AF_INET)) ||
-			    !($$.w2 = parseicmpspec($5, AF_INET6))) {
-				free($3);
-				free($5);
-				YYERROR;
-			}
-			free($3);
-			free($5);
+			$$.w = $3;
+			$$.w2 = $5;
 		}
 		| RETURN {
 			$$.b2 = PFRULE_RETURN;
@@ -2239,7 +2486,45 @@ blockspec	: /* empty */		{
 		}
 		;
 
-dir		: /* empty */			{ $$ = 0; }
+reticmpspec	: STRING			{
+			if (!($$ = parseicmpspec($1, AF_INET))) {
+				free($1);
+				YYERROR;
+			}
+			free($1);
+		}
+		| NUMBER			{
+			u_int8_t		icmptype;
+
+			if ($1 < 0 || $1 > 255) {
+				yyerror("invalid icmp code %lu", $1);
+				YYERROR;
+			}
+			icmptype = returnicmpdefault >> 8;
+			$$ = (icmptype << 8 | $1);
+		}
+		;
+
+reticmp6spec	: STRING			{
+			if (!($$ = parseicmpspec($1, AF_INET6))) {
+				free($1);
+				YYERROR;
+			}
+			free($1);
+		}
+		| NUMBER			{
+			u_int8_t		icmptype;
+
+			if ($1 < 0 || $1 > 255) {
+				yyerror("invalid icmp code %lu", $1);
+				YYERROR;
+			}
+			icmptype = returnicmp6default >> 8;
+			$$ = (icmptype << 8 | $1);
+		}
+		;
+
+dir		: /* empty */			{ $$ = PF_INOUT; }
 		| IN				{ $$ = PF_IN; }
 		| OUT				{ $$ = PF_OUT; }
 		;
@@ -2297,11 +2582,11 @@ logopt		: ALL		{ $$.log = PF_LOG_ALL; $$.logif = 0; }
 
 interface	: /* empty */			{ $$ = NULL; }
 		| ON if_item_not		{ $$ = $2; }
-		| ON '{' if_list '}'		{ $$ = $3; }
+		| ON '{' optnl if_list '}'	{ $$ = $4; }
 		;
 
-if_list		: if_item_not			{ $$ = $1; }
-		| if_list comma if_item_not	{
+if_list		: if_item_not optnl		{ $$ = $1; }
+		| if_list comma if_item_not optnl	{
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
@@ -2340,42 +2625,23 @@ af		: /* empty */			{ $$ = 0; }
 		| INET6				{ $$ = AF_INET6; }
 		;
 
-proto		: /* empty */			{ $$ = NULL; }
-		| PROTO proto_item		{ $$ = $2; }
-		| PROTO '{' proto_list '}'	{ $$ = $3; }
+proto		: /* empty */				{ $$ = NULL; }
+		| PROTO proto_item			{ $$ = $2; }
+		| PROTO '{' optnl proto_list '}'	{ $$ = $4; }
 		;
 
-proto_list	: proto_item			{ $$ = $1; }
-		| proto_list comma proto_item	{
+proto_list	: proto_item optnl		{ $$ = $1; }
+		| proto_list comma proto_item optnl	{
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
 		}
 		;
 
-proto_item	: STRING			{
+proto_item	: protoval			{
 			u_int8_t	pr;
-			u_long		ulval;
 
-			if (atoul($1, &ulval) == 0) {
-				if (ulval > 255) {
-					yyerror("protocol outside range");
-					free($1);
-					YYERROR;
-				}
-				pr = (u_int8_t)ulval;
-			} else {
-				struct protoent	*p;
-
-				p = getprotobyname($1);
-				if (p == NULL) {
-					yyerror("unknown protocol %s", $1);
-					free($1);
-					YYERROR;
-				}
-				pr = p->p_proto;
-			}
-			free($1);
+			pr = (u_int8_t)$1;
 			if (pr == 0) {
 				yyerror("proto 0 cannot be used");
 				YYERROR;
@@ -2389,6 +2655,26 @@ proto_item	: STRING			{
 		}
 		;
 
+protoval	: STRING			{
+			struct protoent	*p;
+
+			p = getprotobyname($1);
+			if (p == NULL) {
+				yyerror("unknown protocol %s", $1);
+				free($1);
+				YYERROR;
+			}
+			$$ = p->p_proto;
+			free($1);
+		}
+		| NUMBER			{
+			if ($1 < 0 || $1 > 255) {
+				yyerror("protocol outside range");
+				YYERROR;
+			}
+		}
+		;
+
 fromto		: ALL				{
 			$$.src.host = NULL;
 			$$.src.port = NULL;
@@ -2405,7 +2691,7 @@ fromto		: ALL				{
 
 os		: /* empty */			{ $$ = NULL; }
 		| OS xos			{ $$ = $2; }
-		| OS '{' os_list '}'		{ $$ = $3; }
+		| OS '{' optnl os_list '}'	{ $$ = $4; }
 		;
 
 xos		: STRING {
@@ -2417,8 +2703,8 @@ xos		: STRING {
 		}
 		;
 
-os_list		: xos				{ $$ = $1; }
-		| os_list comma xos		{
+os_list		: xos optnl 			{ $$ = $1; }
+		| os_list comma xos optnl	{
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
@@ -2460,13 +2746,21 @@ ipportspec	: ipspec			{
 		}
 		;
 
+optnl		: '\n' optnl
+		|
+		;
+
 ipspec		: ANY				{ $$ = NULL; }
 		| xhost				{ $$ = $1; }
-		| '{' host_list '}'		{ $$ = $2; }
+		| '{' optnl host_list '}'	{ $$ = $3; }
+		;
+
+toipspec	: TO ipspec			{ $$ = $2; }
+		| /* empty */			{ $$ = NULL; }
 		;
 
-host_list	: ipspec			{ $$ = $1; }
-		| host_list comma ipspec	{
+host_list	: ipspec optnl			{ $$ = $1; }
+		| host_list comma ipspec optnl	{
 			if ($3 == NULL)
 				$$ = $1;
 			else if ($1 == NULL)
@@ -2506,22 +2800,73 @@ xhost		: not host			{
 		}
 		;
 
-host		: STRING			{
-			if (($$ = host($1)) == NULL)	{
+host		: STRING			{
+			if (($$ = host($1)) == NULL)	{
+				/* error. "any" is handled elsewhere */
+				free($1);
+				yyerror("could not parse host specification");
+				YYERROR;
+			}
+			free($1);
+
+		}
+		| STRING '-' STRING		{
+			struct node_host *b, *e;
+
+			if ((b = host($1)) == NULL || (e = host($3)) == NULL) {
+				free($1);
+				free($3);
+				yyerror("could not parse host specification");
+				YYERROR;
+			}
+			if (b->af != e->af ||
+			    b->addr.type != PF_ADDR_ADDRMASK ||
+			    e->addr.type != PF_ADDR_ADDRMASK ||
+			    unmask(&b->addr.v.a.mask, b->af) !=
+			    (b->af == AF_INET ? 32 : 128) ||
+			    unmask(&e->addr.v.a.mask, e->af) !=
+			    (e->af == AF_INET ? 32 : 128) ||
+			    b->next != NULL || b->not ||
+			    e->next != NULL || e->not) {
+				free(b);
+				free(e);
+				free($1);
+				free($3);
+				yyerror("invalid address range");
+				YYERROR;
+			}
+			memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr,
+			    sizeof(b->addr.v.a.mask));
+			b->addr.type = PF_ADDR_RANGE;
+			$$ = b;
+			free(e);
+			free($1);
+			free($3);
+		}
+		| STRING '/' NUMBER		{
+			char	*buf;
+
+			if (asprintf(&buf, "%s/%lld", $1, (long long)$3) == -1)
+				err(1, "host: asprintf");
+			free($1);
+			if (($$ = host(buf)) == NULL)	{
 				/* error. "any" is handled elsewhere */
-				free($1);
+				free(buf);
 				yyerror("could not parse host specification");
 				YYERROR;
 			}
-			free($1);
-
+			free(buf);
 		}
-		| STRING '/' number		{
+		| NUMBER '/' NUMBER		{
 			char	*buf;
 
-			if (asprintf(&buf, "%s/%u", $1, $3) == -1)
+			/* ie. for 10/8 parsing */
+#ifdef __FreeBSD__
+			if (asprintf(&buf, "%lld/%lld", (long long)$1, (long long)$3) == -1)
+#else
+			if (asprintf(&buf, "%lld/%lld", $1, $3) == -1)
+#endif
 				err(1, "host: asprintf");
-			free($1);
 			if (($$ = host(buf)) == NULL)	{
 				/* error. "any" is handled elsewhere */
 				free(buf);
@@ -2531,9 +2876,13 @@ host		: STRING			{
 			free(buf);
 		}
 		| dynaddr
-		| dynaddr '/' number		{
+		| dynaddr '/' NUMBER		{
 			struct node_host	*n;
 
+			if ($3 < 0 || $3 > 128) {
+				yyerror("bit number too big");
+				YYERROR;
+			}
 			$$ = $1;
 			for (n = $1; n != NULL; n = n->next)
 				set_ipmask(n, $3);
@@ -2578,7 +2927,8 @@ host		: STRING			{
 		}
 		;
 
-number		: STRING			{
+number		: NUMBER
+		| STRING		{
 			u_long	ulval;
 
 			if (atoul($1, &ulval) == -1) {
@@ -2646,18 +2996,18 @@ dynaddr		: '(' STRING ')'		{
 		;
 
 portspec	: port_item			{ $$ = $1; }
-		| '{' port_list '}'		{ $$ = $2; }
+		| '{' optnl port_list '}'	{ $$ = $3; }
 		;
 
-port_list	: port_item			{ $$ = $1; }
-		| port_list comma port_item	{
+port_list	: port_item optnl		{ $$ = $1; }
+		| port_list comma port_item optnl	{
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
 		}
 		;
 
-port_item	: port				{
+port_item	: portrange			{
 			$$ = calloc(1, sizeof(struct node_port));
 			if ($$ == NULL)
 				err(1, "port_item: calloc");
@@ -2670,7 +3020,7 @@ port_item	: port				{
 			$$->next = NULL;
 			$$->tail = $$;
 		}
-		| unaryop port		{
+		| unaryop portrange	{
 			if ($2.t) {
 				yyerror("':' cannot be used with an other "
 				    "port operator");
@@ -2685,7 +3035,7 @@ port_item	: port				{
 			$$->next = NULL;
 			$$->tail = $$;
 		}
-		| port PORTBINARY port		{
+		| portrange PORTBINARY portrange	{
 			if ($1.t || $3.t) {
 				yyerror("':' cannot be used with an other "
 				    "port operator");
@@ -2702,38 +3052,30 @@ port_item	: port				{
 		}
 		;
 
-port		: STRING			{
-			char	*p = strchr($1, ':');
-
-			if (p == NULL) {
-				if (($$.a = getservice($1)) == -1) {
-					free($1);
-					YYERROR;
-				}
-				$$.b = $$.t = 0;
-			} else {
-				int port[2];
+portplain	: numberstring			{
+			if (parseport($1, &$$, 0) == -1) {
+				free($1);
+				YYERROR;
+			}
+			free($1);
+		}
+		;
 
-				*p++ = 0;
-				if ((port[0] = getservice($1)) == -1 ||
-				    (port[1] = getservice(p)) == -1) {
-					free($1);
-					YYERROR;
-				}
-				$$.a = port[0];
-				$$.b = port[1];
-				$$.t = PF_OP_RRG;
+portrange	: numberstring			{
+			if (parseport($1, &$$, PPORT_RANGE) == -1) {
+				free($1);
+				YYERROR;
 			}
 			free($1);
 		}
 		;
 
 uids		: uid_item			{ $$ = $1; }
-		| '{' uid_list '}'		{ $$ = $2; }
+		| '{' optnl uid_list '}'	{ $$ = $3; }
 		;
 
-uid_list	: uid_item			{ $$ = $1; }
-		| uid_list comma uid_item	{
+uid_list	: uid_item optnl		{ $$ = $1; }
+		| uid_list comma uid_item optnl	{
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
@@ -2783,39 +3125,35 @@ uid_item	: uid				{
 		;
 
 uid		: STRING			{
-			u_long	ulval;
-
-			if (atoul($1, &ulval) == -1) {
-				if (!strcmp($1, "unknown"))
-					$$ = UID_MAX;
-				else {
-					struct passwd	*pw;
+			if (!strcmp($1, "unknown"))
+				$$ = UID_MAX;
+			else {
+				struct passwd	*pw;
 
-					if ((pw = getpwnam($1)) == NULL) {
-						yyerror("unknown user %s", $1);
-						free($1);
-						YYERROR;
-					}
-					$$ = pw->pw_uid;
-				}
-			} else {
-				if (ulval >= UID_MAX) {
+				if ((pw = getpwnam($1)) == NULL) {
+					yyerror("unknown user %s", $1);
 					free($1);
-					yyerror("illegal uid value %lu", ulval);
 					YYERROR;
 				}
-				$$ = ulval;
+				$$ = pw->pw_uid;
 			}
 			free($1);
 		}
+		| NUMBER			{
+			if ($1 < 0 || $1 >= UID_MAX) {
+				yyerror("illegal uid value %lu", $1);
+				YYERROR;
+			}
+			$$ = $1;
+		}
 		;
 
 gids		: gid_item			{ $$ = $1; }
-		| '{' gid_list '}'		{ $$ = $2; }
+		| '{' optnl gid_list '}'	{ $$ = $3; }
 		;
 
-gid_list	: gid_item			{ $$ = $1; }
-		| gid_list comma gid_item	{
+gid_list	: gid_item optnl		{ $$ = $1; }
+		| gid_list comma gid_item optnl	{
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
@@ -2865,31 +3203,27 @@ gid_item	: gid				{
 		;
 
 gid		: STRING			{
-			u_long	ulval;
-
-			if (atoul($1, &ulval) == -1) {
-				if (!strcmp($1, "unknown"))
-					$$ = GID_MAX;
-				else {
-					struct group	*grp;
+			if (!strcmp($1, "unknown"))
+				$$ = GID_MAX;
+			else {
+				struct group	*grp;
 
-					if ((grp = getgrnam($1)) == NULL) {
-						yyerror("unknown group %s", $1);
-						free($1);
-						YYERROR;
-					}
-					$$ = grp->gr_gid;
-				}
-			} else {
-				if (ulval >= GID_MAX) {
-					yyerror("illegal gid value %lu", ulval);
+				if ((grp = getgrnam($1)) == NULL) {
+					yyerror("unknown group %s", $1);
 					free($1);
 					YYERROR;
 				}
-				$$ = ulval;
+				$$ = grp->gr_gid;
 			}
 			free($1);
 		}
+		| NUMBER			{
+			if ($1 < 0 || $1 >= GID_MAX) {
+				yyerror("illegal gid value %lu", $1);
+				YYERROR;
+			}
+			$$ = $1;
+		}
 		;
 
 flag		: STRING			{
@@ -2910,22 +3244,22 @@ flags		: FLAGS flag '/' flag	{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
 		| FLAGS ANY		{ $$.b1 = 0; $$.b2 = 0; }
 		;
 
-icmpspec	: ICMPTYPE icmp_item		{ $$ = $2; }
-		| ICMPTYPE '{' icmp_list '}'	{ $$ = $3; }
-		| ICMP6TYPE icmp6_item		{ $$ = $2; }
-		| ICMP6TYPE '{' icmp6_list '}'	{ $$ = $3; }
+icmpspec	: ICMPTYPE icmp_item			{ $$ = $2; }
+		| ICMPTYPE '{' optnl icmp_list '}'	{ $$ = $4; }
+		| ICMP6TYPE icmp6_item			{ $$ = $2; }
+		| ICMP6TYPE '{' optnl icmp6_list '}'	{ $$ = $4; }
 		;
 
-icmp_list	: icmp_item			{ $$ = $1; }
-		| icmp_list comma icmp_item	{
+icmp_list	: icmp_item optnl		{ $$ = $1; }
+		| icmp_list comma icmp_item optnl {
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
 		}
 		;
 
-icmp6_list	: icmp6_item			{ $$ = $1; }
-		| icmp6_list comma icmp6_item	{
+icmp6_list	: icmp6_item optnl		{ $$ = $1; }
+		| icmp6_list comma icmp6_item optnl {
 			$1->tail->next = $3;
 			$1->tail = $3;
 			$$ = $1;
@@ -2944,29 +3278,33 @@ icmp_item	: icmptype		{
 		}
 		| icmptype CODE STRING	{
 			const struct icmpcodeent	*p;
-			u_long				 ulval;
 
-			if (atoul($3, &ulval) == 0) {
-				if (ulval > 255) {
-					free($3);
-					yyerror("illegal icmp-code %lu", ulval);
-					YYERROR;
-				}
-			} else {
-				if ((p = geticmpcodebyname($1-1, $3,
-				    AF_INET)) == NULL) {
-					yyerror("unknown icmp-code %s", $3);
-					free($3);
-					YYERROR;
-				}
-				ulval = p->code;
+			if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) {
+				yyerror("unknown icmp-code %s", $3);
+				free($3);
+				YYERROR;
 			}
+
 			free($3);
 			$$ = calloc(1, sizeof(struct node_icmp));
 			if ($$ == NULL)
 				err(1, "icmp_item: calloc");
 			$$->type = $1;
-			$$->code = ulval + 1;
+			$$->code = p->code + 1;
+			$$->proto = IPPROTO_ICMP;
+			$$->next = NULL;
+			$$->tail = $$;
+		}
+		| icmptype CODE NUMBER	{
+			if ($3 < 0 || $3 > 255) {
+				yyerror("illegal icmp-code %lu", $3);
+				YYERROR;
+			}
+			$$ = calloc(1, sizeof(struct node_icmp));
+			if ($$ == NULL)
+				err(1, "icmp_item: calloc");
+			$$->type = $1;
+			$$->code = $3 + 1;
 			$$->proto = IPPROTO_ICMP;
 			$$->next = NULL;
 			$$->tail = $$;
@@ -2985,30 +3323,33 @@ icmp6_item	: icmp6type		{
 		}
 		| icmp6type CODE STRING	{
 			const struct icmpcodeent	*p;
-			u_long				 ulval;
 
-			if (atoul($3, &ulval) == 0) {
-				if (ulval > 255) {
-					yyerror("illegal icmp6-code %lu",
-					    ulval);
-					free($3);
-					YYERROR;
-				}
-			} else {
-				if ((p = geticmpcodebyname($1-1, $3,
-				    AF_INET6)) == NULL) {
-					yyerror("unknown icmp6-code %s", $3);
-					free($3);
-					YYERROR;
-				}
-				ulval = p->code;
+			if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) {
+				yyerror("unknown icmp6-code %s", $3);
+				free($3);
+				YYERROR;
 			}
 			free($3);
+
+			$$ = calloc(1, sizeof(struct node_icmp));
+			if ($$ == NULL)
+				err(1, "icmp_item: calloc");
+			$$->type = $1;
+			$$->code = p->code + 1;
+			$$->proto = IPPROTO_ICMPV6;
+			$$->next = NULL;
+			$$->tail = $$;
+		}
+		| icmp6type CODE NUMBER	{
+			if ($3 < 0 || $3 > 255) {
+				yyerror("illegal icmp-code %lu", $3);
+				YYERROR;
+			}
 			$$ = calloc(1, sizeof(struct node_icmp));
 			if ($$ == NULL)
 				err(1, "icmp_item: calloc");
 			$$->type = $1;
-			$$->code = ulval + 1;
+			$$->code = $3 + 1;
 			$$->proto = IPPROTO_ICMPV6;
 			$$->next = NULL;
 			$$->tail = $$;
@@ -3017,70 +3358,69 @@ icmp6_item	: icmp6type		{
 
 icmptype	: STRING			{
 			const struct icmptypeent	*p;
-			u_long				 ulval;
 
-			if (atoul($1, &ulval) == 0) {
-				if (ulval > 255) {
-					yyerror("illegal icmp-type %lu", ulval);
-					free($1);
-					YYERROR;
-				}
-				$$ = ulval + 1;
-			} else {
-				if ((p = geticmptypebyname($1, AF_INET)) ==
-				    NULL) {
-					yyerror("unknown icmp-type %s", $1);
-					free($1);
-					YYERROR;
-				}
-				$$ = p->type + 1;
+			if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
+				yyerror("unknown icmp-type %s", $1);
+				free($1);
+				YYERROR;
 			}
+			$$ = p->type + 1;
 			free($1);
 		}
+		| NUMBER			{
+			if ($1 < 0 || $1 > 255) {
+				yyerror("illegal icmp-type %lu", $1);
+				YYERROR;
+			}
+			$$ = $1 + 1;
+		}
 		;
 
 icmp6type	: STRING			{
 			const struct icmptypeent	*p;
-			u_long				 ulval;
 
-			if (atoul($1, &ulval) == 0) {
-				if (ulval > 255) {
-					yyerror("illegal icmp6-type %lu",
-					    ulval);
-					free($1);
-					YYERROR;
-				}
-				$$ = ulval + 1;
-			} else {
-				if ((p = geticmptypebyname($1, AF_INET6)) ==
-				    NULL) {
-					yyerror("unknown icmp6-type %s", $1);
-					free($1);
-					YYERROR;
-				}
-				$$ = p->type + 1;
+			if ((p = geticmptypebyname($1, AF_INET6)) ==
+			    NULL) {
+				yyerror("unknown icmp6-type %s", $1);
+				free($1);
+				YYERROR;
 			}
+			$$ = p->type + 1;
 			free($1);
 		}
+		| NUMBER			{
+			if ($1 < 0 || $1 > 255) {
+				yyerror("illegal icmp6-type %lu", $1);
+				YYERROR;
+			}
+			$$ = $1 + 1;
+		}
 		;
 
-tos		: TOS STRING			{
-			if (!strcmp($2, "lowdelay"))
+tos	: STRING			{
+			if (!strcmp($1, "lowdelay"))
 				$$ = IPTOS_LOWDELAY;
-			else if (!strcmp($2, "throughput"))
+			else if (!strcmp($1, "throughput"))
 				$$ = IPTOS_THROUGHPUT;
-			else if (!strcmp($2, "reliability"))
+			else if (!strcmp($1, "reliability"))
 				$$ = IPTOS_RELIABILITY;
-			else if ($2[0] == '0' && $2[1] == 'x')
-				$$ = strtoul($2, NULL, 16);
+			else if ($1[0] == '0' && $1[1] == 'x')
+				$$ = strtoul($1, NULL, 16);
 			else
-				$$ = strtoul($2, NULL, 10);
+				$$ = 0;		/* flag bad argument */
 			if (!$$ || $$ > 255) {
-				yyerror("illegal tos value %s", $2);
-				free($2);
+				yyerror("illegal tos value %s", $1);
+				free($1);
+				YYERROR;
+			}
+			free($1);
+		}
+		| NUMBER			{
+			$$ = $1;
+			if (!$$ || $$ > 255) {
+				yyerror("illegal tos value %s", $1);
 				YYERROR;
 			}
-			free($2);
 		}
 		;
 
@@ -3134,7 +3474,11 @@ state_opt_list	: state_opt_item		{ $$ = $1; }
 		}
 		;
 
-state_opt_item	: MAXIMUM number		{
+state_opt_item	: MAXIMUM NUMBER		{
+			if ($2 < 0 || $2 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			$$ = calloc(1, sizeof(struct node_state_opt));
 			if ($$ == NULL)
 				err(1, "state_opt_item: calloc");
@@ -3151,7 +3495,11 @@ state_opt_item	: MAXIMUM number		{
 			$$->next = NULL;
 			$$->tail = $$;
 		}
-		| MAXSRCSTATES number			{
+		| MAXSRCSTATES NUMBER			{
+			if ($2 < 0 || $2 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			$$ = calloc(1, sizeof(struct node_state_opt));
 			if ($$ == NULL)
 				err(1, "state_opt_item: calloc");
@@ -3160,7 +3508,11 @@ state_opt_item	: MAXIMUM number		{
 			$$->next = NULL;
 			$$->tail = $$;
 		}
-		| MAXSRCCONN number			{
+		| MAXSRCCONN NUMBER			{
+			if ($2 < 0 || $2 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			$$ = calloc(1, sizeof(struct node_state_opt));
 			if ($$ == NULL)
 				err(1, "state_opt_item: calloc");
@@ -3169,7 +3521,12 @@ state_opt_item	: MAXIMUM number		{
 			$$->next = NULL;
 			$$->tail = $$;
 		}
-		| MAXSRCCONNRATE number '/' number	{
+		| MAXSRCCONNRATE NUMBER '/' NUMBER	{
+			if ($2 < 0 || $2 > UINT_MAX ||
+			    $4 < 0 || $4 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			$$ = calloc(1, sizeof(struct node_state_opt));
 			if ($$ == NULL)
 				err(1, "state_opt_item: calloc");
@@ -3197,7 +3554,11 @@ state_opt_item	: MAXIMUM number		{
 			$$->next = NULL;
 			$$->tail = $$;
 		}
-		| MAXSRCNODES number			{
+		| MAXSRCNODES NUMBER			{
+			if ($2 < 0 || $2 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			$$ = calloc(1, sizeof(struct node_state_opt));
 			if ($$ == NULL)
 				err(1, "state_opt_item: calloc");
@@ -3232,9 +3593,21 @@ state_opt_item	: MAXIMUM number		{
 			$$->next = NULL;
 			$$->tail = $$;
 		}
-		| STRING number			{
+		| PFLOW {
+			$$ = calloc(1, sizeof(struct node_state_opt));
+			if ($$ == NULL)
+				err(1, "state_opt_item: calloc");
+			$$->type = PF_STATE_OPT_PFLOW;
+			$$->next = NULL;
+			$$->tail = $$;
+		}
+		| STRING NUMBER			{
 			int	i;
 
+			if ($2 < 0 || $2 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			for (i = 0; pf_timeouts[i].name &&
 			    strcmp(pf_timeouts[i].name, $1); ++i)
 				;	/* nothing */
@@ -3267,9 +3640,11 @@ label		: LABEL STRING			{
 
 qname		: QUEUE STRING				{
 			$$.qname = $2;
+			$$.pqname = NULL;
 		}
 		| QUEUE '(' STRING ')'			{
 			$$.qname = $3;
+			$$.pqname = NULL;
 		}
 		| QUEUE '(' STRING comma STRING ')'	{
 			$$.qname = $3;
@@ -3281,44 +3656,21 @@ no		: /* empty */			{ $$ = 0; }
 		| NO				{ $$ = 1; }
 		;
 
-rport		: STRING			{
-			char	*p = strchr($1, ':');
-
-			if (p == NULL) {
-				if (($$.a = getservice($1)) == -1) {
-					free($1);
-					YYERROR;
-				}
-				$$.b = $$.t = 0;
-			} else if (!strcmp(p+1, "*")) {
-				*p = 0;
-				if (($$.a = getservice($1)) == -1) {
-					free($1);
-					YYERROR;
-				}
-				$$.b = 0;
-				$$.t = 1;
-			} else {
-				*p++ = 0;
-				if (($$.a = getservice($1)) == -1 ||
-				    ($$.b = getservice(p)) == -1) {
-					free($1);
-					YYERROR;
-				}
-				if ($$.a == $$.b)
-					$$.b = 0;
-				$$.t = 0;
+portstar	: numberstring			{
+			if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) {
+				free($1);
+				YYERROR;
 			}
 			free($1);
 		}
 		;
 
 redirspec	: host				{ $$ = $1; }
-		| '{' redir_host_list '}'	{ $$ = $2; }
+		| '{' optnl redir_host_list '}'	{ $$ = $3; }
 		;
 
-redir_host_list	: host				{ $$ = $1; }
-		| redir_host_list comma host	{
+redir_host_list	: host optnl			{ $$ = $1; }
+		| redir_host_list comma host optnl {
 			$1->tail->next = $3;
 			$1->tail = $3->tail;
 			$$ = $1;
@@ -3333,7 +3685,7 @@ redirpool	: /* empty */			{ $$ = NULL; }
 			$$->host = $2;
 			$$->rport.a = $$->rport.b = $$->rport.t = 0;
 		}
-		| ARROW redirspec PORT rport	{
+		| ARROW redirspec PORT portstar	{
 			$$ = calloc(1, sizeof(struct redirection));
 			if ($$ == NULL)
 				err(1, "redirection: calloc");
@@ -3459,7 +3811,7 @@ redirection	: /* empty */			{ $$ = NULL; }
 			$$->host = $2;
 			$$->rport.a = $$->rport.b = $$->rport.t = 0;
 		}
-		| ARROW host PORT rport	{
+		| ARROW host PORT portstar	{
 			$$ = calloc(1, sizeof(struct redirection));
 			if ($$ == NULL)
 				err(1, "redirection: calloc");
@@ -3468,17 +3820,13 @@ redirection	: /* empty */			{ $$ = NULL; }
 		}
 		;
 
-/* ifdef __FreeBSD__ */
-natpass		: /* empty */	{ $$.b1 = $$.b2 = 0; $$.w2 = 0; }
+natpasslog	: /* empty */	{ $$.b1 = $$.b2 = 0; $$.w2 = 0; }
 		| PASS		{ $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; }
-/* else 
-natpass		:  empty 	{ $$.b1 = $$.b2 = 0; }
-		| PASS		{ $$.b1 = 1; $$.b2 = 0; }
- * endif */
 		| PASS log	{ $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
+		| log		{ $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; }
 		;
 
-nataction	: no NAT natpass {
+nataction	: no NAT natpasslog {
 			if ($1 && $3.b1) {
 				yyerror("\"pass\" not valid with \"no\"");
 				YYERROR;
@@ -3491,7 +3839,7 @@ nataction	: no NAT natpass {
 			$$.w = $3.b2;
 			$$.w2 = $3.w2;
 		}
-		| no RDR natpass {
+		| no RDR natpasslog {
 			if ($1 && $3.b1) {
 				yyerror("\"pass\" not valid with \"no\"");
 				YYERROR;
@@ -3665,7 +4013,7 @@ natrule		: nataction interface af proto fromto tag tagged rtable
 		}
 		;
 
-binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
+binatrule	: no BINAT natpasslog interface af proto FROM host toipspec tag
 		    tagged rtable redirection
 		{
 			struct pf_rule		binat;
@@ -3673,7 +4021,7 @@ binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
 
 			if (check_rulestate(PFCTL_STATE_NAT))
 				YYERROR;
-			if (disallow_urpf_failed($10, "\"urpf-failed\" is not "
+			if (disallow_urpf_failed($9, "\"urpf-failed\" is not "
 			    "permitted as a binat destination"))
 				YYERROR;
 
@@ -3693,11 +4041,11 @@ binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
 			binat.af = $5;
 			if (!binat.af && $8 != NULL && $8->af)
 				binat.af = $8->af;
-			if (!binat.af && $10 != NULL && $10->af)
-				binat.af = $10->af;
+			if (!binat.af && $9 != NULL && $9->af)
+				binat.af = $9->af;
 
-			if (!binat.af && $14 != NULL && $14->host)
-				binat.af = $14->host->af;
+			if (!binat.af && $13 != NULL && $13->host)
+				binat.af = $13->host->af;
 			if (!binat.af) {
 				yyerror("address family (inet/inet6) "
 				    "undefined");
@@ -3711,22 +4059,22 @@ binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
 				free($4);
 			}
 
-			if ($11 != NULL)
-				if (strlcpy(binat.tagname, $11,
+			if ($10 != NULL)
+				if (strlcpy(binat.tagname, $10,
 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
 					yyerror("tag too long, max %u chars",
 					    PF_TAG_NAME_SIZE - 1);
 					YYERROR;
 				}
-			if ($12.name)
-				if (strlcpy(binat.match_tagname, $12.name,
+			if ($11.name)
+				if (strlcpy(binat.match_tagname, $11.name,
 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
 					yyerror("tag too long, max %u chars",
 					    PF_TAG_NAME_SIZE - 1);
 					YYERROR;
 				}
-			binat.match_tag_not = $12.neg;
-			binat.rtableid = $13;
+			binat.match_tag_not = $11.neg;
+			binat.rtableid = $12;
 
 			if ($6 != NULL) {
 				binat.proto = $6->proto;
@@ -3740,12 +4088,12 @@ binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
 			    "interface (%s) as the source address of a binat "
 			    "rule"))
 				YYERROR;
-			if ($14 != NULL && $14->host != NULL && disallow_table(
-			    $14->host, "invalid use of table <%s> as the "
+			if ($13 != NULL && $13->host != NULL && disallow_table(
+			    $13->host, "invalid use of table <%s> as the "
 			    "redirect address of a binat rule"))
 				YYERROR;
-			if ($14 != NULL && $14->host != NULL && disallow_alias(
-			    $14->host, "invalid use of interface (%s) as the "
+			if ($13 != NULL && $13->host != NULL && disallow_alias(
+			    $13->host, "invalid use of interface (%s) as the "
 			    "redirect address of a binat rule"))
 				YYERROR;
 
@@ -3766,51 +4114,51 @@ binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
 				    sizeof(binat.src.addr));
 				free($8);
 			}
-			if ($10 != NULL) {
-				if ($10->next) {
+			if ($9 != NULL) {
+				if ($9->next) {
 					yyerror("multiple binat ip addresses");
 					YYERROR;
 				}
-				if ($10->af != binat.af && $10->af) {
+				if ($9->af != binat.af && $9->af) {
 					yyerror("binat ip versions must match");
 					YYERROR;
 				}
-				if (check_netmask($10, binat.af))
+				if (check_netmask($9, binat.af))
 					YYERROR;
-				memcpy(&binat.dst.addr, &$10->addr,
+				memcpy(&binat.dst.addr, &$9->addr,
 				    sizeof(binat.dst.addr));
-				binat.dst.neg = $10->not;
-				free($10);
+				binat.dst.neg = $9->not;
+				free($9);
 			}
 
 			if (binat.action == PF_NOBINAT) {
-				if ($14 != NULL) {
+				if ($13 != NULL) {
 					yyerror("'no binat' rule does not need"
 					    " '->'");
 					YYERROR;
 				}
 			} else {
-				if ($14 == NULL || $14->host == NULL) {
+				if ($13 == NULL || $13->host == NULL) {
 					yyerror("'binat' rule requires"
 					    " '-> address'");
 					YYERROR;
 				}
 
-				remove_invalid_hosts(&$14->host, &binat.af);
-				if (invalid_redirect($14->host, binat.af))
+				remove_invalid_hosts(&$13->host, &binat.af);
+				if (invalid_redirect($13->host, binat.af))
 					YYERROR;
-				if ($14->host->next != NULL) {
+				if ($13->host->next != NULL) {
 					yyerror("binat rule must redirect to "
 					    "a single address");
 					YYERROR;
 				}
-				if (check_netmask($14->host, binat.af))
+				if (check_netmask($13->host, binat.af))
 					YYERROR;
 
 				if (!PF_AZERO(&binat.src.addr.v.a.mask,
 				    binat.af) &&
 				    !PF_AEQ(&binat.src.addr.v.a.mask,
-				    &$14->host->addr.v.a.mask, binat.af)) {
+				    &$13->host->addr.v.a.mask, binat.af)) {
 					yyerror("'binat' source mask and "
 					    "redirect mask must be the same");
 					YYERROR;
@@ -3820,12 +4168,12 @@ binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
 				pa = calloc(1, sizeof(struct pf_pooladdr));
 				if (pa == NULL)
 					err(1, "binat: calloc");
-				pa->addr = $14->host->addr;
+				pa->addr = $13->host->addr;
 				pa->ifname[0] = 0;
 				TAILQ_INSERT_TAIL(&binat.rpool.list,
 				    pa, entries);
 
-				free($14);
+				free($13);
 			}
 
 			pfctl_add_rule(pf, &binat, "");
@@ -3841,17 +4189,12 @@ tagged		: /* empty */		{ $$.neg = 0; $$.name = NULL; }
 		;
 
 rtable		: /* empty */		{ $$ = -1; }
-		| RTABLE number		{
-#ifdef __FreeBSD__
-			yyerror("rtable id not supported in FreeBSD, yet");
-			YYERROR;
-#else
-			if ($2 > RT_TABLEID_MAX || $2 < 0) {
+		| RTABLE NUMBER		{
+			if ($2 < 0 /* || $2 > RT_TABLEID_MAX */ ) {
 				yyerror("invalid rtable id");
 				YYERROR;
 			}
 			$$ = $2;
-#endif
 		}
 		;
 
@@ -3870,8 +4213,8 @@ route_host	: STRING			{
 		}
 		;
 
-route_host_list	: route_host				{ $$ = $1; }
-		| route_host_list comma route_host	{
+route_host_list	: route_host optnl			{ $$ = $1; }
+		| route_host_list comma route_host optnl {
 			if ($1->af == 0)
 				$1->af = $3->af;
 			if ($1->af != $3->af) {
@@ -3886,7 +4229,7 @@ route_host_list	: route_host				{ $$ = $1; }
 		;
 
 routespec	: route_host			{ $$ = $1; }
-		| '{' route_host_list '}'	{ $$ = $2; }
+		| '{' optnl route_host_list '}'	{ $$ = $3; }
 		;
 
 route		: /* empty */			{
@@ -3922,12 +4265,16 @@ route		: /* empty */			{
 		}
 		;
 
-timeout_spec	: STRING number
+timeout_spec	: STRING NUMBER
 		{
 			if (check_rulestate(PFCTL_STATE_OPTION)) {
 				free($1);
 				YYERROR;
 			}
+			if ($2 < 0 || $2 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
 				yyerror("unknown timeout %s", $1);
 				free($1);
@@ -3937,16 +4284,20 @@ timeout_spec	: STRING number
 		}
 		;
 
-timeout_list	: timeout_list comma timeout_spec
-		| timeout_spec
+timeout_list	: timeout_list comma timeout_spec optnl
+		| timeout_spec optnl
 		;
 
-limit_spec	: STRING number
+limit_spec	: STRING NUMBER
 		{
 			if (check_rulestate(PFCTL_STATE_OPTION)) {
 				free($1);
 				YYERROR;
 			}
+			if ($2 < 0 || $2 > UINT_MAX) {
+				yyerror("only positive values permitted");
+				YYERROR;
+			}
 			if (pfctl_set_limit(pf, $1, $2) != 0) {
 				yyerror("unable to set limit %s %u", $1, $2);
 				free($1);
@@ -3956,8 +4307,8 @@ limit_spec	: STRING number
 		}
 		;
 
-limit_list	: limit_list comma limit_spec
-		| limit_spec
+limit_list	: limit_list comma limit_spec optnl
+		| limit_spec optnl
 		;
 
 comma		: ','
@@ -3992,11 +4343,10 @@ int
 yyerror(const char *fmt, ...)
 {
 	va_list		 ap;
-	extern char	*infile;
 
-	errors = 1;
+	file->errors++;
 	va_start(ap, fmt);
-	fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
+	fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
 	vfprintf(stderr, fmt, ap);
 	fprintf(stderr, "\n");
 	va_end(ap);
@@ -4914,6 +5264,8 @@ lookup(char *s)
 		{ "code",		CODE},
 		{ "crop",		FRAGCROP},
 		{ "debug",		DEBUG},
+		{ "divert-reply",	DIVERTREPLY},
+		{ "divert-to",		DIVERTTO},
 		{ "drop",		DROP},
 		{ "drop-ovl",		FRAGDROP},
 		{ "dup-to",		DUPTO},
@@ -4934,6 +5286,7 @@ lookup(char *s)
 		{ "icmp6-type",		ICMP6TYPE},
 		{ "if-bound",		IFBOUND},
 		{ "in",			IN},
+		{ "include",		INCLUDE},
 		{ "inet",		INET},
 		{ "inet6",		INET6},
 		{ "keep",		KEEP},
@@ -4963,6 +5316,7 @@ lookup(char *s)
 		{ "out",		OUT},
 		{ "overload",		OVERLOAD},
 		{ "pass",		PASS},
+		{ "pflow",		PFLOW},
 		{ "port",		PORT},
 		{ "priority",		PRIORITY},
 		{ "priq",		PRIQ},
@@ -4991,11 +5345,13 @@ lookup(char *s)
 		{ "ruleset-optimization",	RULESET_OPTIMIZATION},
 		{ "scrub",		SCRUB},
 		{ "set",		SET},
+		{ "set-tos",		SETTOS},
 		{ "skip",		SKIP},
 		{ "sloppy",		SLOPPY},
 		{ "source-hash",	SOURCEHASH},
 		{ "source-track",	SOURCETRACK},
 		{ "state",		STATE},
+		{ "state-defaults",	STATEDEFAULTS},
 		{ "state-policy",	STATEPOLICY},
 		{ "static-port",	STATICPORT},
 		{ "sticky-address",	STICKYADDRESS},
@@ -5036,9 +5392,9 @@ char	 pushback_buffer[MAXPUSHBACK];
 int	 pushback_index = 0;
 
 int
-lgetc(FILE *f)
+lgetc(int quotec)
 {
-	int	c, next;
+	int		c, next;
 
 	if (parsebuf) {
 		/* Read character from the parsebuffer instead of input. */
@@ -5054,24 +5410,31 @@ lgetc(FILE *f)
 	if (pushback_index)
 		return (pushback_buffer[--pushback_index]);
 
-	while ((c = getc(f)) == '\\') {
-		next = getc(f);
+	if (quotec) {
+		if ((c = getc(file->stream)) == EOF) {
+			yyerror("reached end of file while parsing quoted string");
+			if (popfile() == EOF)
+				return (EOF);
+			return (quotec);
+		}
+		return (c);
+	}
+
+	while ((c = getc(file->stream)) == '\\') {
+		next = getc(file->stream);
 		if (next != '\n') {
 			c = next;
 			break;
 		}
-		yylval.lineno = lineno;
-		lineno++;
-	}
-	if (c == '\t' || c == ' ') {
-		/* Compress blanks to a single space. */
-		do {
-			c = getc(f);
-		} while (c == '\t' || c == ' ');
-		ungetc(c, f);
-		c = ' ';
+		yylval.lineno = file->lineno;
+		file->lineno++;
 	}
 
+	while (c == EOF) {
+		if (popfile() == EOF)
+			return (EOF);
+		c = getc(file->stream);
+	}
 	return (c);
 }
 
@@ -5097,13 +5460,15 @@ findeol(void)
 	int	c;
 
 	parsebuf = NULL;
-	pushback_index = 0;
 
 	/* skip to either EOF or the first real EOL */
 	while (1) {
-		c = lgetc(fin);
+		if (pushback_index)
+			c = pushback_buffer[--pushback_index];
+		else
+			c = lgetc(0);
 		if (c == '\n') {
-			lineno++;
+			file->lineno++;
 			break;
 		}
 		if (c == EOF)
@@ -5117,21 +5482,21 @@ yylex(void)
 {
 	char	 buf[8096];
 	char	*p, *val;
-	int	 endc, c, next;
+	int	 quotec, next, c;
 	int	 token;
 
 top:
 	p = buf;
-	while ((c = lgetc(fin)) == ' ')
+	while ((c = lgetc(0)) == ' ' || c == '\t')
 		; /* nothing */
 
-	yylval.lineno = lineno;
+	yylval.lineno = file->lineno;
 	if (c == '#')
-		while ((c = lgetc(fin)) != '\n' && c != EOF)
+		while ((c = lgetc(0)) != '\n' && c != EOF)
 			; /* nothing */
 	if (c == '$' && parsebuf == NULL) {
 		while (1) {
-			if ((c = lgetc(fin)) == EOF)
+			if ((c = lgetc(0)) == EOF)
 				return (0);
 
 			if (p + 1 >= buf + sizeof(buf) - 1) {
@@ -5159,17 +5524,25 @@ top:
 	switch (c) {
 	case '\'':
 	case '"':
-		endc = c;
+		quotec = c;
 		while (1) {
-			if ((c = lgetc(fin)) == EOF)
+			if ((c = lgetc(quotec)) == EOF)
 				return (0);
-			if (c == endc) {
-				*p = '\0';
-				break;
-			}
 			if (c == '\n') {
-				lineno++;
+				file->lineno++;
 				continue;
+			} else if (c == '\\') {
+				if ((next = lgetc(quotec)) == EOF)
+					return (0);
+				if (next == quotec || c == ' ' || c == '\t')
+					c = next;
+				else if (next == '\n')
+					continue;
+				else
+					lungetc(next);
+			} else if (c == quotec) {
+				*p = '\0';
+				break;
 			}
 			if (p + 1 >= buf + sizeof(buf) - 1) {
 				yyerror("string too long");
@@ -5182,7 +5555,7 @@ top:
 			err(1, "yylex: strdup");
 		return (STRING);
 	case '<':
-		next = lgetc(fin);
+		next = lgetc(0);
 		if (next == '>') {
 			yylval.v.i = PF_OP_XRG;
 			return (PORTBINARY);
@@ -5190,7 +5563,7 @@ top:
 		lungetc(next);
 		break;
 	case '>':
-		next = lgetc(fin);
+		next = lgetc(0);
 		if (next == '<') {
 			yylval.v.i = PF_OP_IRG;
 			return (PORTBINARY);
@@ -5198,13 +5571,49 @@ top:
 		lungetc(next);
 		break;
 	case '-':
-		next = lgetc(fin);
+		next = lgetc(0);
 		if (next == '>')
 			return (ARROW);
 		lungetc(next);
 		break;
 	}
 
+#define allowed_to_end_number(x) \
+	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
+
+	if (c == '-' || isdigit(c)) {
+		do {
+			*p++ = c;
+			if ((unsigned)(p-buf) >= sizeof(buf)) {
+				yyerror("string too long");
+				return (findeol());
+			}
+		} while ((c = lgetc(0)) != EOF && isdigit(c));
+		lungetc(c);
+		if (p == buf + 1 && buf[0] == '-')
+			goto nodigits;
+		if (c == EOF || allowed_to_end_number(c)) {
+			const char *errstr = NULL;
+
+			*p = '\0';
+			yylval.v.number = strtonum(buf, LLONG_MIN,
+			    LLONG_MAX, &errstr);
+			if (errstr) {
+				yyerror("\"%s\" invalid number: %s",
+				    buf, errstr);
+				return (findeol());
+			}
+			return (NUMBER);
+		} else {
+nodigits:
+			while (p > buf + 1)
+				lungetc(*--p);
+			c = *--p;
+			if (c == '-')
+				return (c);
+		}
+	}
+
 #define allowed_in_string(x) \
 	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
 	x != '{' && x != '}' && x != '<' && x != '>' && \
@@ -5218,7 +5627,7 @@ top:
 				yyerror("string too long");
 				return (findeol());
 			}
-		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
+		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
 		lungetc(c);
 		*p = '\0';
 		if ((token = lookup(buf)) == STRING)
@@ -5227,8 +5636,8 @@ top:
 		return (token);
 	}
 	if (c == '\n') {
-		yylval.lineno = lineno;
-		lineno++;
+		yylval.lineno = file->lineno;
+		file->lineno++;
 	}
 	if (c == EOF)
 		return (0);
@@ -5236,13 +5645,84 @@ top:
 }
 
 int
-parse_rules(FILE *input, struct pfctl *xpf)
+check_file_secrecy(int fd, const char *fname)
+{
+	struct stat	st;
+
+	if (fstat(fd, &st)) {
+		warn("cannot stat %s", fname);
+		return (-1);
+	}
+	if (st.st_uid != 0 && st.st_uid != getuid()) {
+		warnx("%s: owner not root or current user", fname);
+		return (-1);
+	}
+	if (st.st_mode & (S_IRWXG | S_IRWXO)) {
+		warnx("%s: group/world readable/writeable", fname);
+		return (-1);
+	}
+	return (0);
+}
+
+struct file *
+pushfile(const char *name, int secret)
+{
+	struct file	*nfile;
+
+	if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
+	    (nfile->name = strdup(name)) == NULL) {
+		warn("malloc");
+		return (NULL);
+	}
+	if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) {
+		nfile->stream = stdin;
+		free(nfile->name);
+		if ((nfile->name = strdup("stdin")) == NULL) {
+			warn("strdup");
+			free(nfile);
+			return (NULL);
+		}
+	} else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
+		warn("%s", nfile->name);
+		free(nfile->name);
+		free(nfile);
+		return (NULL);
+	} else if (secret &&
+	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
+		fclose(nfile->stream);
+		free(nfile->name);
+		free(nfile);
+		return (NULL);
+	}
+	nfile->lineno = 1;
+	TAILQ_INSERT_TAIL(&files, nfile, entry);
+	return (nfile);
+}
+
+int
+popfile(void)
+{
+	struct file	*prev;
+
+	if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
+		prev->errors += file->errors;
+		TAILQ_REMOVE(&files, file, entry);
+		fclose(file->stream);
+		free(file->name);
+		free(file);
+		file = prev;
+		return (0);
+	}
+	return (EOF);
+}
+
+int
+parse_config(char *filename, struct pfctl *xpf)
 {
-	struct sym	*sym, *next;
+	int		 errors = 0;
+	struct sym	*sym;
 
-	fin = input;
 	pf = xpf;
-	lineno = 1;
 	errors = 0;
 	rulestate = PFCTL_STATE_NONE;
 	returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
@@ -5251,34 +5731,36 @@ parse_rules(FILE *input, struct pfctl *xpf)
 	blockpolicy = PFRULE_DROP;
 	require_order = 1;
 
+	if ((file = pushfile(filename, 0)) == NULL) {
+		warn("cannot open the main config file!");
+		return (-1);
+	}
+
 	yyparse();
+	errors = file->errors;
+	popfile();
 
 	/* Free macros and check which have not been used. */
-	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
-		next = TAILQ_NEXT(sym, entries);
+	while ((sym = TAILQ_FIRST(&symhead))) {
 		if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
 			fprintf(stderr, "warning: macro '%s' not "
 			    "used\n", sym->nam);
 		free(sym->nam);
 		free(sym->val);
-		TAILQ_REMOVE(&symhead, sym, entries);
+		TAILQ_REMOVE(&symhead, sym, entry);
 		free(sym);
 	}
 
 	return (errors ? -1 : 0);
 }
 
-/*
- * Over-designed efficiency is a French and German concept, so how about
- * we wait until they discover this ugliness and make it all fancy.
- */
 int
 symset(const char *nam, const char *val, int persist)
 {
 	struct sym	*sym;
 
 	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
-	    sym = TAILQ_NEXT(sym, entries))
+	    sym = TAILQ_NEXT(sym, entry))
 		;	/* nothing */
 
 	if (sym != NULL) {
@@ -5287,7 +5769,7 @@ symset(const char *nam, const char *val, int persist)
 		else {
 			free(sym->nam);
 			free(sym->val);
-			TAILQ_REMOVE(&symhead, sym, entries);
+			TAILQ_REMOVE(&symhead, sym, entry);
 			free(sym);
 		}
 	}
@@ -5307,7 +5789,7 @@ symset(const char *nam, const char *val, int persist)
 	}
 	sym->used = 0;
 	sym->persist = persist;
-	TAILQ_INSERT_TAIL(&symhead, sym, entries);
+	TAILQ_INSERT_TAIL(&symhead, sym, entry);
 	return (0);
 }
 
@@ -5336,7 +5818,7 @@ symget(const char *nam)
 {
 	struct sym	*sym;
 
-	TAILQ_FOREACH(sym, &symhead, entries)
+	TAILQ_FOREACH(sym, &symhead, entry)
 		if (strcmp(nam, sym->nam) == 0) {
 			sym->used = 1;
 			return (sym->val);
@@ -5519,20 +6001,50 @@ parseicmpspec(char *w, sa_family_t af)
 }
 
 int
+parseport(char *port, struct range *r, int extensions)
+{
+	char	*p = strchr(port, ':');
+
+	if (p == NULL) {
+		if ((r->a = getservice(port)) == -1)
+			return (-1);
+		r->b = 0;
+		r->t = PF_OP_NONE;
+		return (0);
+	}
+	if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) {
+		*p = 0;
+		if ((r->a = getservice(port)) == -1)
+			return (-1);
+		r->b = 0;
+		r->t = PF_OP_IRG;
+		return (0);
+	}
+	if ((extensions & PPORT_RANGE)) {
+		*p++ = 0;
+		if ((r->a = getservice(port)) == -1 ||
+		    (r->b = getservice(p)) == -1)
+			return (-1);
+		if (r->a == r->b) {
+			r->b = 0;
+			r->t = PF_OP_NONE;
+		} else
+			r->t = PF_OP_RRG;
+		return (0);
+	}
+	return (-1);
+}
+
+int
 pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
 {
 	struct loadanchors	*la;
-	FILE			*fin;
 
 	TAILQ_FOREACH(la, &loadanchorshead, entries) {
 		if (pf->opts & PF_OPT_VERBOSE)
 			fprintf(stderr, "\nLoading anchor %s from %s\n",
 			    la->anchorname, la->filename);
-		if ((fin = pfctl_fopen(la->filename, "r")) == NULL) {
-			warn("%s", la->filename);
-			continue;
-		}
-		if (pfctl_rules(dev, la->filename, fin, pf->opts, pf->optimize,
+		if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize,
 		    la->anchorname, trans) == -1)
 			return (-1);
 	}
diff --git a/contrib/pf/pfctl/pf_print_state.c b/contrib/pf/pfctl/pf_print_state.c
index 02a39b3..0698516 100644
--- a/contrib/pf/pfctl/pf_print_state.c
+++ b/contrib/pf/pfctl/pf_print_state.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf_print_state.c,v 1.44 2007/03/01 17:20:53 deraadt Exp $	*/
+/*	$OpenBSD: pf_print_state.c,v 1.52 2008/08/12 16:40:18 david Exp $	*/
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -35,7 +35,10 @@ __FBSDID("$FreeBSD$");
 
 #include 
 #include 
+#ifdef __FreeBSD__
 #include 
+#define	betoh64	be64toh
+#endif
 #include 
 #define TCPSTATES
 #include 
@@ -83,6 +86,19 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
 		else
 			printf("<%s>", addr->v.tblname);
 		return;
+	case PF_ADDR_RANGE: {
+		char buf[48];
+
+		if (inet_ntop(af, &addr->v.a.addr, buf, sizeof(buf)) == NULL)
+			printf("?");
+		else
+			printf("%s", buf);
+		if (inet_ntop(af, &addr->v.a.mask, buf, sizeof(buf)) == NULL)
+			printf(" - ?");
+		else
+			printf(" - %s", buf);
+		break;
+	}
 	case PF_ADDR_ADDRMASK:
 		if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
 		    PF_AZERO(&addr->v.a.mask, AF_INET6))
@@ -112,7 +128,8 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
 	}
 
 	/* mask if not _both_ address and mask are zero */
-	if (!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
+	if (addr->type != PF_ADDR_RANGE &&
+	    !(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
 	    PF_AZERO(&addr->v.a.mask, AF_INET6))) {
 		int bits = unmask(&addr->v.a.mask, af);
 
@@ -155,17 +172,15 @@ print_name(struct pf_addr *addr, sa_family_t af)
 }
 
 void
-print_host(struct pf_state_host *h, sa_family_t af, int opts)
+print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts)
 {
-	u_int16_t p = ntohs(h->port);
-
 	if (opts & PF_OPT_USEDNS)
-		print_name(&h->addr, af);
+		print_name(addr, af);
 	else {
 		struct pf_addr_wrap aw;
 
 		memset(&aw, 0, sizeof(aw));
-		aw.v.a.addr = h->addr;
+		aw.v.a.addr = *addr;
 		if (af == AF_INET)
 			aw.v.a.mask.addr32[0] = 0xffffffff;
 		else {
@@ -175,57 +190,72 @@ print_host(struct pf_state_host *h, sa_family_t af, int opts)
 		print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
 	}
 
-	if (p) {
+	if (port) {
 		if (af == AF_INET)
-			printf(":%u", p);
+			printf(":%u", ntohs(port));
 		else
-			printf("[%u]", p);
+			printf("[%u]", ntohs(port));
 	}
 }
 
 void
-print_seq(struct pf_state_peer *p)
+print_seq(struct pfsync_state_peer *p)
 {
 	if (p->seqdiff)
-		printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
-		    p->seqdiff);
+		printf("[%u + %u](+%u)", ntohl(p->seqlo),
+		    ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
 	else
-		printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
+		printf("[%u + %u]", ntohl(p->seqlo),
+		    ntohl(p->seqhi) - ntohl(p->seqlo));
 }
 
 void
-print_state(struct pf_state *s, int opts)
+print_state(struct pfsync_state *s, int opts)
 {
-	struct pf_state_peer *src, *dst;
+	struct pfsync_state_peer *src, *dst;
+	struct pfsync_state_key *sk, *nk;
 	struct protoent *p;
 	int min, sec;
 
 	if (s->direction == PF_OUT) {
 		src = &s->src;
 		dst = &s->dst;
+		sk = &s->key[PF_SK_STACK];
+		nk = &s->key[PF_SK_WIRE];
+		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
+			sk->port[0] = nk->port[0];
 	} else {
 		src = &s->dst;
 		dst = &s->src;
+		sk = &s->key[PF_SK_WIRE];
+		nk = &s->key[PF_SK_STACK];
+		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6) 
+			sk->port[1] = nk->port[1];
 	}
-	printf("%s ", s->u.ifname);
+	printf("%s ", s->ifname);
 	if ((p = getprotobynumber(s->proto)) != NULL)
 		printf("%s ", p->p_name);
 	else
 		printf("%u ", s->proto);
-	if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
-	    (s->lan.port != s->gwy.port)) {
-		print_host(&s->lan, s->af, opts);
-		if (s->direction == PF_OUT)
-			printf(" -> ");
-		else
-			printf(" <- ");
+
+	print_host(&nk->addr[1], nk->port[1], s->af, opts);
+	if (PF_ANEQ(&nk->addr[1], &sk->addr[1], s->af) ||
+	    nk->port[1] != sk->port[1]) {
+		printf(" (");
+		print_host(&sk->addr[1], sk->port[1], s->af, opts);
+		printf(")");
 	}
-	print_host(&s->gwy, s->af, opts);
 	if (s->direction == PF_OUT)
 		printf(" -> ");
 	else
 		printf(" <- ");
-	print_host(&s->ext, s->af, opts);
+	print_host(&nk->addr[0], nk->port[0], s->af, opts);
+	if (PF_ANEQ(&nk->addr[0], &sk->addr[0], s->af) ||
+	    nk->port[0] != sk->port[0]) {
+		printf(" (");
+		print_host(&sk->addr[0], sk->port[0], s->af, opts);
+		printf(")");
+	}
 
 	printf("    ");
 	if (s->proto == IPPROTO_TCP) {
@@ -271,45 +301,63 @@ print_state(struct pf_state *s, int opts)
 	}
 
 	if (opts & PF_OPT_VERBOSE) {
-		sec = s->creation % 60;
-		s->creation /= 60;
-		min = s->creation % 60;
-		s->creation /= 60;
-		printf("   age %.2u:%.2u:%.2u", s->creation, min, sec);
-		sec = s->expire % 60;
-		s->expire /= 60;
-		min = s->expire % 60;
-		s->expire /= 60;
-		printf(", expires in %.2u:%.2u:%.2u", s->expire, min, sec);
+		u_int64_t packets[2];
+		u_int64_t bytes[2];
+		u_int32_t creation = ntohl(s->creation);
+		u_int32_t expire = ntohl(s->expire);
+
+		sec = creation % 60;
+		creation /= 60;
+		min = creation % 60;
+		creation /= 60;
+		printf("   age %.2u:%.2u:%.2u", creation, min, sec);
+		sec = expire % 60;
+		expire /= 60;
+		min = expire % 60;
+		expire /= 60;
+		printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
+
+		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
+		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
+		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
+		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
 		printf(", %llu:%llu pkts, %llu:%llu bytes",
 #ifdef __FreeBSD__
-		    (unsigned long long)s->packets[0],
-		    (unsigned long long)s->packets[1],
-		    (unsigned long long)s->bytes[0],
-		    (unsigned long long)s->bytes[1]);
+		    (unsigned long long)betoh64(packets[0]),
+		    (unsigned long long)betoh64(packets[1]),
+		    (unsigned long long)betoh64(bytes[0]),
+		    (unsigned long long)betoh64(bytes[1]));
 #else
-		    s->packets[0], s->packets[1], s->bytes[0], s->bytes[1]);
+		    betoh64(packets[0]),
+		    betoh64(packets[1]),
+		    betoh64(bytes[0]),
+		    betoh64(bytes[1]));
 #endif
-		if (s->anchor.nr != -1)
-			printf(", anchor %u", s->anchor.nr);
-		if (s->rule.nr != -1)
-			printf(", rule %u", s->rule.nr);
+		if (ntohl(s->anchor) != -1)
+			printf(", anchor %u", ntohl(s->anchor));
+		if (ntohl(s->rule) != -1)
+			printf(", rule %u", ntohl(s->rule));
 		if (s->state_flags & PFSTATE_SLOPPY)
 			printf(", sloppy");
-		if (s->src_node != NULL)
+		if (s->state_flags & PFSTATE_PFLOW)
+			printf(", pflow");
+		if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
 			printf(", source-track");
-		if (s->nat_src_node != NULL)
+		if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
 			printf(", sticky-address");
 		printf("\n");
 	}
 	if (opts & PF_OPT_VERBOSE2) {
-		printf("   id: %016llx creatorid: %08x%s\n",
+		u_int64_t id;
+
+		bcopy(&s->id, &id, sizeof(u_int64_t));
+		printf("   id: %016llx creatorid: %08x",
 #ifdef __FreeBSD__
-		    (unsigned long long)be64toh(s->id), ntohl(s->creatorid),
+		    (unsigned long long)betoh64(id), ntohl(s->creatorid));
 #else
-		    betoh64(s->id), ntohl(s->creatorid),
+		    betoh64(id), ntohl(s->creatorid));
 #endif
-		    ((s->sync_flags & PFSTATE_NOSYNC) ? " (no-sync)" : ""));
+		printf("\n");
 	}
 }
 
diff --git a/contrib/pf/pfctl/pfctl.8 b/contrib/pf/pfctl/pfctl.8
index 917a859..0730443 100644
--- a/contrib/pf/pfctl/pfctl.8
+++ b/contrib/pf/pfctl/pfctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pfctl.8,v 1.128 2007/01/30 21:01:56 jmc Exp $
+.\" $OpenBSD: pfctl.8,v 1.138 2008/06/10 20:55:02 mcbride Exp $
 .\"
 .\" Copyright (c) 2001 Kjell Wooding.  All rights reserved.
 .\"
@@ -26,12 +26,12 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 13, 2011
+.Dd June 21, 2011
 .Dt PFCTL 8
 .Os
 .Sh NAME
 .Nm pfctl
-.Nd "control the packet filter (PF) and network address translation (NAT) device"
+.Nd control the packet filter (PF) device
 .Sh SYNOPSIS
 .Nm pfctl
 .Bk -words
@@ -43,15 +43,18 @@
 .Op Fl f Ar file
 .Op Fl i Ar interface
 .Op Fl K Ar host | network
-.Op Fl k Ar host | network
-.Op Fl o Op Ar level
+.Xo
+.Oo Fl k
+.Ar host | network | label | id
+.Oc Xc
+.Op Fl o Ar level
 .Op Fl p Ar device
 .Op Fl s Ar modifier
-.Oo
-.Fl t Ar table
+.Xo
+.Oo Fl t Ar table
 .Fl T Ar command
-.Op Ar address ...
-.Oc
+.Op Ar address ... Oc
+.Xc
 .Op Fl x Ar level
 .Ek
 .Sh DESCRIPTION
@@ -85,7 +88,7 @@ When the variable
 is set to
 .Dv YES
 in
-.Xr rc.conf.local 5 ,
+.Xr rc.conf.local 8 ,
 the rule file specified with the variable
 .Va pf_rules
 is loaded automatically by the
@@ -211,7 +214,7 @@ Flush the NAT rules.
 Flush the queue rules.
 .It Fl F Cm rules
 Flush the filter rules.
-.It Fl F Cm state
+.It Fl F Cm states
 Flush the state table (NAT and filter).
 .It Fl F Cm Sources
 Flush the source tracking table.
@@ -251,22 +254,28 @@ or
 .Fl K Ar network
 option may be specified, which will kill all the source tracking
 entries from the first host/network to the second.
-.It Fl k Ar host | network
-Kill all of the state entries originating from the specified
-.Ar host
+.It Xo
+.Fl k
+.Ar host | network | label | id
+.Xc
+Kill all of the state entries matching the specified
+.Ar host ,
+.Ar network ,
+.Ar label ,
 or
-.Ar network .
+.Ar id .
+.Pp
+For example, to kill all of the state entries originating from
+.Dq host :
+.Pp
+.Dl # pfctl -k host
+.Pp
 A second
 .Fl k Ar host
 or
 .Fl k Ar network
 option may be specified, which will kill all the state entries
 from the first host/network to the second.
-For example, to kill all of the state entries originating from
-.Dq host :
-.Pp
-.Dl # pfctl -k host
-.Pp
 To kill all of the state entries from
 .Dq host1
 to
@@ -283,6 +292,32 @@ To kill all states with the target
 .Dq host2 :
 .Pp
 .Dl # pfctl -k 0.0.0.0/0 -k host2
+.Pp
+It is also possible to kill states by rule label or state ID.
+In this mode the first
+.Fl k
+argument is used to specify the type
+of the second argument.
+The following command would kill all states that have been created
+from rules carrying the label
+.Dq foobar :
+.Pp
+.Dl # pfctl -k label -k foobar
+.Pp
+To kill one specific state by its unique state ID
+(as shown by pfctl -s state -vv),
+use the
+.Ar id
+modifier and as a second argument the state ID and optional creator ID.
+To kill a state with ID 4823e84500000003 use:
+.Pp
+.Dl # pfctl -k id -k 4823e84500000003
+.Pp
+To kill a state with ID 4823e84500000018 created from a backup
+firewall with hostid 00000002 use:
+.Pp
+.Dl # pfctl -k id -k 4823e84500000018/2
+.Pp
 .It Fl m
 Merge in explicitly given options without resetting those
 which are omitted.
@@ -298,58 +333,20 @@ Do not actually load rules, just parse them.
 .It Fl O
 Load only the options present in the rule file.
 Other rules and options are ignored.
-.It Fl o Op Ar level
-Control the ruleset optimizer.
-The ruleset optimizer attempts to improve rulesets by removing rule
-duplication and making better use of rule ordering.
+.It Fl o Ar level
+Control the ruleset optimizer, overriding any rule file settings.
 .Pp
 .Bl -tag -width xxxxxxxxxxxx -compact
 .It Fl o Cm none
 Disable the ruleset optimizer.
 .It Fl o Cm basic
 Enable basic ruleset optimizations.
+This is the default behaviour.
 .It Fl o Cm profile
 Enable basic ruleset optimizations with profiling.
 .El
-.Pp
-.Cm basic
-optimization does does four things:
-.Pp
-.Bl -enum -compact
-.It
-remove duplicate rules
-.It
-remove rules that are a subset of another rule
-.It
-combine multiple rules into a table when advantageous
-.It
-re-order the rules to improve evaluation performance
-.El
-.Pp
-If
-.Cm profile
-is specified, the currently loaded ruleset will be examined as a feedback
-profile to tailor the optimization of the
-.Ar quick
-rules to the actual network behavior.
-.Pp
-It is important to note that the ruleset optimizer will modify the ruleset
-to improve performance.
-A side effect of the ruleset modification is that per-rule accounting
-statistics will have different meanings than before.
-If per-rule accounting is important for billing purposes or whatnot, either
-the ruleset optimizer should not be used or a
-.Ar label
-field should be added to all of the accounting rules to act as optimization
-barriers.
-.Pp
-To retain compatibility with previous behaviour, a single
-.Fl o
-without any options will enable
-.Cm basic
-optimizations, and a second
-.Fl o
-will enable profiling.
+For further information on the ruleset optimizer, see
+.Xr pf.conf 5 .
 .It Fl P
 Do not perform service name lookup for port specific rules,
 instead display the ports numerically.
@@ -407,7 +404,7 @@ If
 .Fl v
 is specified, all anchors attached under the target anchor will be
 displayed recursively.
-.It Fl s Cm state
+.It Fl s Cm states
 Show the contents of the state table.
 .It Fl s Cm Sources
 Show the contents of the source tracking table.
@@ -418,7 +415,7 @@ When used together with
 source tracking statistics are also shown.
 .It Fl s Cm labels
 Show per-rule statistics (label, evaluations, packets total, bytes total,
-packets in, bytes in, packets out, bytes out) of
+packets in, bytes in, packets out, bytes out, state creations) of
 filter rules with labels, useful for accounting.
 .It Fl s Cm timeouts
 Show the current global timeouts.
@@ -529,7 +526,7 @@ attributes.
 The address/network has been cleared (statistics).
 .El
 .Pp
-Each table maintains a set of counters that can be retrieved using the
+Each table can maintain a set of counters that can be retrieved using the
 .Fl v
 flag of
 .Nm .
@@ -540,7 +537,7 @@ FTP server.
 The following commands configure the firewall and send 10 pings to the FTP
 server:
 .Bd -literal -offset indent
-# printf "table  { ftp.openbsd.org }\en \e
+# printf "table  counters { ftp.openbsd.org }\en \e
     pass out to \en" | pfctl -f-
 # ping -qc10 ftp.openbsd.org
 .Ed
@@ -574,7 +571,7 @@ the number of rules which reference the table, and the global
 packet statistics for the whole table:
 .Bd -literal -offset indent
 # pfctl -vvsTables
---a-r-  test
+--a-r-C test
     Addresses:   1
     Cleared:     Thu Feb 13 18:55:18 2003
     References:  [ Anchors: 0        Rules: 1        ]
@@ -634,6 +631,8 @@ For tables which are referenced (used) by rules.
 .It h
 This flag is set when a table in the main ruleset is hidden by one or more
 tables of the same name from anchors attached below it.
+.It C
+This flag is set when per-address counters are enabled on the table.
 .El
 .It Fl t Ar table
 Specify the name of the table.
diff --git a/contrib/pf/pfctl/pfctl.c b/contrib/pf/pfctl/pfctl.c
index e76261b..8b07a2b 100644
--- a/contrib/pf/pfctl/pfctl.c
+++ b/contrib/pf/pfctl/pfctl.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pfctl.c,v 1.262 2007/03/01 17:20:53 deraadt Exp $ */
+/*	$OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -39,6 +39,10 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
+#ifdef __FreeBSD__
+#include 
+#endif
+
 #include 
 #include 
 #include 
@@ -59,10 +63,6 @@ __FBSDID("$FreeBSD$");
 #include "pfctl_parser.h"
 #include "pfctl.h"
 
-#ifdef __FreeBSD__
-#define HTONL(x)	(x) = htonl((__uint32_t)(x))
-#endif
-
 void	 usage(void);
 int	 pfctl_enable(int, int);
 int	 pfctl_disable(int, int);
@@ -75,7 +75,9 @@ int	 pfctl_clear_src_nodes(int, int);
 int	 pfctl_clear_states(int, const char *, int);
 void	 pfctl_addrprefix(char *, struct pf_addr *);
 int	 pfctl_kill_src_nodes(int, const char *, int);
-int	 pfctl_kill_states(int, const char *, int);
+int	 pfctl_net_kill_states(int, const char *, int);
+int	 pfctl_label_kill_states(int, const char *, int);
+int	 pfctl_id_kill_states(int, const char *, int);
 void	 pfctl_init_options(struct pfctl *);
 int	 pfctl_load_options(struct pfctl *);
 int	 pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
@@ -126,8 +128,6 @@ int		 dev = -1;
 int		 first_title = 1;
 int		 labels = 0;
 
-const char	*infile;
-
 #define INDENT(d, o)	do {						\
 				if (o) {				\
 					int i;				\
@@ -208,11 +208,11 @@ static const struct {
 
 static const char *clearopt_list[] = {
 	"nat", "queue", "rules", "Sources",
-	"state", "info", "Tables", "osfp", "all", NULL
+	"states", "info", "Tables", "osfp", "all", NULL
 };
 
 static const char *showopt_list[] = {
-	"nat", "queue", "rules", "Anchors", "Sources", "state", "info",
+	"nat", "queue", "rules", "Anchors", "Sources", "states", "info",
 	"Interfaces", "labels", "timeouts", "memory", "Tables", "osfp",
 	"all", NULL
 };
@@ -227,7 +227,7 @@ static const char *debugopt_list[] = {
 };
 
 static const char *optiopt_list[] = {
-	"o", "none", "basic", "profile", NULL
+	"none", "basic", "profile", NULL
 };
 
 void
@@ -237,10 +237,11 @@ usage(void)
 
 	fprintf(stderr, "usage: %s [-AdeghmNnOPqRrvz] ", __progname);
 	fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
-	fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] ");
-	fprintf(stderr, "[-k host | network ]\n");
-	fprintf(stderr, "\t[-o [level]] [-p device] [-s modifier ]\n");
-	fprintf(stderr, "\t[-t table -T command [address ...]] [-x level]\n");
+	fprintf(stderr, "\t[-f file] [-i interface] [-K host | network]\n");
+	fprintf(stderr, "\t[-k host | network | label | id] ");
+	fprintf(stderr, "[-o level] [-p device]\n");
+	fprintf(stderr, "\t[-s modifier] ");
+	fprintf(stderr, "[-t table -T command [address ...]] [-x level]\n");
 	exit(1);
 }
 
@@ -389,7 +390,7 @@ pfctl_clear_states(int dev, const char *iface, int opts)
 	if (ioctl(dev, DIOCCLRSTATES, &psk))
 		err(1, "DIOCCLRSTATES");
 	if ((opts & PF_OPT_QUIET) == 0)
-		fprintf(stderr, "%d states cleared\n", psk.psk_af);
+		fprintf(stderr, "%d states cleared\n", psk.psk_killed);
 	return (0);
 }
 
@@ -528,17 +529,13 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
 
 				if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
 					err(1, "DIOCKILLSRCNODES");
-				killed += psnk.psnk_af;
-				/* fixup psnk.psnk_af */
-				psnk.psnk_af = resp[1]->ai_family;
+				killed += psnk.psnk_killed;
 			}
 			freeaddrinfo(res[1]);
 		} else {
 			if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
 				err(1, "DIOCKILLSRCNODES");
-			killed += psnk.psnk_af;
-			/* fixup psnk.psnk_af */
-			psnk.psnk_af = res[0]->ai_family;
+			killed += psnk.psnk_killed;
 		}
 	}
 
@@ -551,7 +548,7 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
 }
 
 int
-pfctl_kill_states(int dev, const char *iface, int opts)
+pfctl_net_kill_states(int dev, const char *iface, int opts)
 {
 	struct pfioc_state_kill psk;
 	struct addrinfo *res[2], *resp[2];
@@ -638,17 +635,13 @@ pfctl_kill_states(int dev, const char *iface, int opts)
 
 				if (ioctl(dev, DIOCKILLSTATES, &psk))
 					err(1, "DIOCKILLSTATES");
-				killed += psk.psk_af;
-				/* fixup psk.psk_af */
-				psk.psk_af = resp[1]->ai_family;
+				killed += psk.psk_killed;
 			}
 			freeaddrinfo(res[1]);
 		} else {
 			if (ioctl(dev, DIOCKILLSTATES, &psk))
 				err(1, "DIOCKILLSTATES");
-			killed += psk.psk_af;
-			/* fixup psk.psk_af */
-			psk.psk_af = res[0]->ai_family;
+			killed += psk.psk_killed;
 		}
 	}
 
@@ -661,6 +654,68 @@ pfctl_kill_states(int dev, const char *iface, int opts)
 }
 
 int
+pfctl_label_kill_states(int dev, const char *iface, int opts)
+{
+	struct pfioc_state_kill psk;
+
+	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+		warnx("no label specified");
+		usage();
+	}
+	memset(&psk, 0, sizeof(psk));
+	if (iface != NULL && strlcpy(psk.psk_ifname, iface,
+	    sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
+		errx(1, "invalid interface: %s", iface);
+
+	if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >=
+	    sizeof(psk.psk_label))
+		errx(1, "label too long: %s", state_kill[1]);
+
+	if (ioctl(dev, DIOCKILLSTATES, &psk))
+		err(1, "DIOCKILLSTATES");
+
+	if ((opts & PF_OPT_QUIET) == 0)
+		fprintf(stderr, "killed %d states\n", psk.psk_killed);
+
+	return (0);
+}
+
+int
+pfctl_id_kill_states(int dev, const char *iface, int opts)
+{
+	struct pfioc_state_kill psk;
+	
+	if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+		warnx("no id specified");
+		usage();
+	}
+
+	memset(&psk, 0, sizeof(psk));
+	if ((sscanf(state_kill[1], "%jx/%x",
+	    &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2)
+		HTONL(psk.psk_pfcmp.creatorid);
+	else if ((sscanf(state_kill[1], "%jx", &psk.psk_pfcmp.id)) == 1) {
+		psk.psk_pfcmp.creatorid = 0;
+	} else {
+		warnx("wrong id format specified");
+		usage();
+	}
+	if (psk.psk_pfcmp.id == 0) {
+		warnx("cannot kill id 0");
+		usage();
+	}
+
+	psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id);
+	if (ioctl(dev, DIOCKILLSTATES, &psk))
+		err(1, "DIOCKILLSTATES");
+
+	if ((opts & PF_OPT_QUIET) == 0)
+		fprintf(stderr, "killed %d states\n", psk.psk_killed);
+
+	return (0);
+}
+
+int
 pfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr,
     u_int32_t ticket, int r_action, char *anchorname)
 {
@@ -747,10 +802,12 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts)
 			    (unsigned long long)(rule->packets[0] +
 			    rule->packets[1]),
 			    (unsigned long long)(rule->bytes[0] +
-			    rule->bytes[1]), rule->states);
+			    rule->bytes[1]), rule->states_cur);
 		if (!(opts & PF_OPT_DEBUG))
-			printf("  [ Inserted: uid %u pid %u ]\n",
-			    (unsigned)rule->cuid, (unsigned)rule->cpid);
+			printf("  [ Inserted: uid %u pid %u "
+			    "State Creations: %-6u]\n",
+			    (unsigned)rule->cuid, (unsigned)rule->cpid,
+			    rule->states_tot);
 	}
 }
 
@@ -818,19 +875,6 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 
 		switch (format) {
 		case PFCTL_SHOW_LABELS:
-			if (pr.rule.label[0]) {
-				printf("%s ", pr.rule.label);
-				printf("%llu %llu %llu %llu %llu %llu %llu\n",
-				    (unsigned long long)pr.rule.evaluations,
-				    (unsigned long long)(pr.rule.packets[0] +
-				    pr.rule.packets[1]),
-				    (unsigned long long)(pr.rule.bytes[0] +
-				    pr.rule.bytes[1]),
-				    (unsigned long long)pr.rule.packets[0],
-				    (unsigned long long)pr.rule.bytes[0],
-				    (unsigned long long)pr.rule.packets[1],
-				    (unsigned long long)pr.rule.bytes[1]);
-			}
 			break;
 		case PFCTL_SHOW_RULES:
 			if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
@@ -864,8 +908,9 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 		switch (format) {
 		case PFCTL_SHOW_LABELS:
 			if (pr.rule.label[0]) {
-				printf("%s ", pr.rule.label);
-				printf("%llu %llu %llu %llu %llu %llu %llu\n",
+				printf("%s %llu %llu %llu %llu"
+				    " %llu %llu %llu %llu\n",
+				    pr.rule.label,
 				    (unsigned long long)pr.rule.evaluations,
 				    (unsigned long long)(pr.rule.packets[0] +
 				    pr.rule.packets[1]),
@@ -874,7 +919,8 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
 				    (unsigned long long)pr.rule.packets[0],
 				    (unsigned long long)pr.rule.bytes[0],
 				    (unsigned long long)pr.rule.packets[1],
-				    (unsigned long long)pr.rule.bytes[1]);
+				    (unsigned long long)pr.rule.bytes[1],
+				    (unsigned long long)pr.rule.states_tot);
 			}
 			break;
 		case PFCTL_SHOW_RULES:
@@ -967,7 +1013,7 @@ pfctl_show_src_nodes(int dev, int opts)
 	struct pfioc_src_nodes psn;
 	struct pf_src_node *p;
 	char *inbuf = NULL, *newinbuf = NULL;
-	unsigned len = 0;
+	unsigned int len = 0;
 	int i;
 
 	memset(&psn, 0, sizeof(psn));
@@ -1010,9 +1056,9 @@ int
 pfctl_show_states(int dev, const char *iface, int opts)
 {
 	struct pfioc_states ps;
-	struct pf_state *p;
+	struct pfsync_state *p;
 	char *inbuf = NULL, *newinbuf = NULL;
-	unsigned len = 0;
+	unsigned int len = 0;
 	int i, dotitle = (opts & PF_OPT_SHOWALL);
 
 	memset(&ps, 0, sizeof(ps));
@@ -1041,7 +1087,7 @@ pfctl_show_states(int dev, const char *iface, int opts)
 	}
 	p = ps.ps_states;
 	for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) {
-		if (iface != NULL && strcmp(p->u.ifname, iface))
+		if (iface != NULL && strcmp(p->ifname, iface))
 			continue;
 		if (dotitle) {
 			pfctl_print_title("STATES:");
@@ -1163,7 +1209,7 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
 		r->anchor->ruleset.anchor = r->anchor;
 		if (strlcpy(r->anchor->path, anchor_call,
 		    sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
-                        errx(1, "pfctl_add_rule: strlcpy");
+			errx(1, "pfctl_add_rule: strlcpy");
 		if ((p = strrchr(anchor_call, '/')) != NULL) {
 			if (!strlen(p))
 				err(1, "pfctl_add_rule: bad anchor name %s",
@@ -1172,7 +1218,7 @@ pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call)
 			p = (char *)anchor_call;
 		if (strlcpy(r->anchor->name, p,
 		    sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
-                        errx(1, "pfctl_add_rule: strlcpy");
+			errx(1, "pfctl_add_rule: strlcpy");
 	}
 
 	if ((rule = calloc(1, sizeof(*rule))) == NULL)
@@ -1197,7 +1243,7 @@ pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a)
 			return (1);
 	}
 	if (a == pf->astack[0] && ((altqsupport &&
-	     (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
+	    (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) {
 		if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path))
 			return (2);
 	}
@@ -1350,7 +1396,7 @@ pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
 }
 
 int
-pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
+pfctl_rules(int dev, char *filename, int opts, int optimize,
     char *anchorname, struct pfr_buffer *trans)
 {
 #define ERR(x) do { warn(x); goto _error; } while(0)
@@ -1386,7 +1432,6 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
 	if (strlcpy(trs.pfrt_anchor, anchorname,
 	    sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
 		ERRX("pfctl_rules: strlcpy");
-	infile = filename;
 	pf.dev = dev;
 	pf.opts = opts;
 	pf.optimize = optimize;
@@ -1430,7 +1475,7 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
 			    pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname);
 	}
 
-	if (parse_rules(fin, &pf) < 0) {
+	if (parse_config(filename, &pf) < 0) {
 		if ((opts & PF_OPT_NOACTION) == 0)
 			ERRX("Syntax error in config file: "
 			    "pf rules not loaded");
@@ -1456,11 +1501,6 @@ pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize,
 		if (check_commit_altq(dev, opts) != 0)
 			ERRX("errors in altq config");
 
-	if (fin != stdin) {
-		fclose(fin);
-		fin = NULL;
-	}
-
 	/* process "load anchor" directives */
 	if (!anchorname[0])
 		if (pfctl_load_anchors(dev, &pf, t) == -1)
@@ -1482,8 +1522,6 @@ _error:
 				err(1, "DIOCXROLLBACK");
 		exit(1);
 	} else {		/* sub ruleset */
-		if (fin != NULL && fin != stdin)
-			fclose(fin);
 		return (-1);
 	}
 
@@ -1515,7 +1553,8 @@ pfctl_fopen(const char *name, const char *mode)
 void
 pfctl_init_options(struct pfctl *pf)
 {
-	int mib[2], mem;
+	int64_t mem;
+	int mib[2];
 	size_t size;
 
 	pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
@@ -1546,9 +1585,14 @@ pfctl_init_options(struct pfctl *pf)
 	pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
 
 	mib[0] = CTL_HW;
+#ifdef __FreeBSD__
 	mib[1] = HW_PHYSMEM;
+#else
+	mib[1] = HW_PHYSMEM64;
+#endif
 	size = sizeof(mem);
-	(void) sysctl(mib, 2, &mem, &size, NULL, 0);
+	if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1)
+		err(1, "sysctl");
 	if (mem <= 100*1024*1024)
 		pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL; 
 
@@ -1572,7 +1616,7 @@ pfctl_load_options(struct pfctl *pf)
 	}
 
 	/*
-	 * If we've set the limit, but havn't explicitly set adaptive
+	 * If we've set the limit, but haven't explicitly set adaptive
 	 * timeouts, do it now with a start of 60% and end of 120%.
 	 */
 	if (pf->limit_set[PF_LIMIT_STATES] &&
@@ -1897,9 +1941,6 @@ pfctl_debug(int dev, u_int32_t level, int opts)
 int
 pfctl_test_altqsupport(int dev, int opts)
 {
-#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ)
-	return (0);
-#else
 	struct pfioc_altq pa;
 
 	if (ioctl(dev, DIOCGETALTQS, &pa)) {
@@ -1912,7 +1953,6 @@ pfctl_test_altqsupport(int dev, int opts)
 			err(1, "DIOCGETALTQS");
 	}
 	return (1);
-#endif
 }
 
 int
@@ -1971,16 +2011,15 @@ main(int argc, char *argv[])
 	int	 ch;
 	int	 mode = O_RDONLY;
 	int	 opts = 0;
-	int	 optimize = 0;
+	int	 optimize = PF_OPTIMIZE_BASIC;
 	char	 anchorname[MAXPATHLEN];
 	char	*path;
-	FILE	*fin = NULL;
 
 	if (argc < 2)
 		usage();
 
 	while ((ch = getopt(argc, argv,
-	    "a:AdD:eqf:F:ghi:k:K:mnNOo::Pp:rRs:t:T:vx:z")) != -1) {
+	    "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) {
 		switch (ch) {
 		case 'a':
 			anchoropt = optarg;
@@ -2056,24 +2095,11 @@ main(int argc, char *argv[])
 			loadopt |= PFCTL_FLAG_FILTER;
 			break;
 		case 'o':
-			if (optarg) {
-				optiopt = pfctl_lookup_option(optarg,
-				    optiopt_list);
-					if (optiopt == NULL) {
-					warnx("Unknown optimization '%s'",
-					    optarg);
-					usage();
-				}
-			}
-			if (opts & PF_OPT_OPTIMIZE) {
-				if (optiopt != NULL) {
-					warnx("Cannot specify -o multiple times"
-					    "with optimizer level");
-					usage();
-				}
-				optimize |= PF_OPTIMIZE_PROFILE;
+			optiopt = pfctl_lookup_option(optarg, optiopt_list);
+			if (optiopt == NULL) {
+				warnx("Unknown optimization '%s'", optarg);
+				usage();
 			}
-			optimize |= PF_OPTIMIZE_BASIC;
 			opts |= PF_OPT_OPTIMIZE;
 			break;
 		case 'O':
@@ -2303,8 +2329,14 @@ main(int argc, char *argv[])
 			break;
 		}
 	}
-	if (state_killers)
-		pfctl_kill_states(dev, ifaceopt, opts);
+	if (state_killers) {
+		if (!strcmp(state_kill[0], "label"))
+			pfctl_label_kill_states(dev, ifaceopt, opts);
+		else if (!strcmp(state_kill[0], "id"))
+			pfctl_id_kill_states(dev, ifaceopt, opts);
+		else
+			pfctl_net_kill_states(dev, ifaceopt, opts);
+	}
 
 	if (src_node_killers)
 		pfctl_kill_src_nodes(dev, ifaceopt, opts);
@@ -2329,15 +2361,6 @@ main(int argc, char *argv[])
 		}
 	}
 
- 	if (rulesopt != NULL) {
-		if (strcmp(rulesopt, "-") == 0) {
-			fin = stdin;
-			rulesopt = "stdin";
-		} else {
-			if ((fin = pfctl_fopen(rulesopt, "r")) == NULL)
-				err(1, "%s", rulesopt);
-		}
-	}
 	if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
 	    !anchorname[0])
 		if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
@@ -2352,7 +2375,7 @@ main(int argc, char *argv[])
 		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
 			errx(1, "anchor names beginning with '_' cannot "
 			    "be modified from the command line");
-		if (pfctl_rules(dev, rulesopt, fin, opts, optimize,
+		if (pfctl_rules(dev, rulesopt, opts, optimize,
 		    anchorname, NULL))
 			error = 1;
 		else if (!(opts & PF_OPT_NOACTION) &&
diff --git a/contrib/pf/pfctl/pfctl.h b/contrib/pf/pfctl/pfctl.h
index 98a1bef..2c69bc2 100644
--- a/contrib/pf/pfctl/pfctl.h
+++ b/contrib/pf/pfctl/pfctl.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pfctl.h,v 1.40 2007/02/09 11:25:27 henning Exp $ */
+/*	$OpenBSD: pfctl.h,v 1.42 2007/12/05 12:01:47 chl Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -49,7 +49,6 @@ struct pfr_buffer {
 	    (var) != NULL;				\
 	    (var) = pfr_buf_next((buf), (var)))
 
-void	 pfr_set_fd(int);
 int	 pfr_get_fd(void);
 int	 pfr_clr_tables(struct pfr_table *, int *, int);
 int	 pfr_add_tables(struct pfr_table *, int, int *, int);
@@ -64,9 +63,7 @@ int	 pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
 	    int *, int *, int *, int);
 int	 pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
 int	 pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
-int	 pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
 int	 pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
-int	 pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
 int	 pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
 	    int *, int, int);
 void	 pfr_buf_clear(struct pfr_buffer *);
@@ -91,6 +88,8 @@ FILE	*pfctl_fopen(const char *, const char *);
 
 #ifdef __FreeBSD__
 extern int altqsupport;
+extern int dummynetsupport;
+#define	HTONL(x)		(x) = htonl((__uint32_t)(x))
 #endif
 
 #ifndef DEFAULT_PRIORITY
@@ -117,9 +116,9 @@ struct pf_altq	*pfaltq_lookup(const char *);
 char		*rate2str(double);
 
 void	 print_addr(struct pf_addr_wrap *, sa_family_t, int);
-void	 print_host(struct pf_state_host *, sa_family_t, int);
-void	 print_seq(struct pf_state_peer *);
-void	 print_state(struct pf_state *, int);
+void	 print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
+void	 print_seq(struct pfsync_state_peer *);
+void	 print_state(struct pfsync_state *, int);
 int	 unmask(struct pf_addr *, sa_family_t);
 
 int	 pfctl_cmdline_symset(char *);
diff --git a/contrib/pf/pfctl/pfctl_altq.c b/contrib/pf/pfctl/pfctl_altq.c
index b90e7c6..40e11d5 100644
--- a/contrib/pf/pfctl/pfctl_altq.c
+++ b/contrib/pf/pfctl/pfctl_altq.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pfctl_altq.c,v 1.91 2006/11/28 00:08:50 henning Exp $	*/
+/*	$OpenBSD: pfctl_altq.c,v 1.93 2007/10/15 02:16:35 deraadt Exp $	*/
 
 /*
  * Copyright (c) 2002
@@ -21,7 +21,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
-#include 
+#include 
 #include 
 #include 
 
@@ -78,7 +78,7 @@ static int		 gsc_add_seg(struct gen_sc *, double, double, double,
 static double		 sc_x2y(struct service_curve *, double);
 
 #ifdef __FreeBSD__
-u_int32_t	 getifspeed(int, char *);
+u_int32_t	getifspeed(int, char *);
 #else
 u_int32_t	 getifspeed(char *);
 #endif
@@ -145,8 +145,8 @@ qname_to_qid(const char *qname)
 }
 
 void
-print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
-	struct node_queue_opt *qopts)
+print_altq(const struct pf_altq *a, unsigned int level,
+    struct node_queue_bw *bw, struct node_queue_opt *qopts)
 {
 	if (a->qname[0] != 0) {
 		print_queue(a, level, bw, 1, qopts);
@@ -157,6 +157,7 @@ print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
 	if (a->local_flags & PFALTQ_FLAG_IF_REMOVED)
 		printf("INACTIVE ");
 #endif
+
 	printf("altq on %s ", a->ifname);
 
 	switch (a->scheduler) {
@@ -186,10 +187,11 @@ print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
 }
 
 void
-print_queue(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw,
-    int print_interface, struct node_queue_opt *qopts)
+print_queue(const struct pf_altq *a, unsigned int level,
+    struct node_queue_bw *bw, int print_interface,
+    struct node_queue_opt *qopts)
 {
-	unsigned	i;
+	unsigned int	i;
 
 #ifdef __FreeBSD__
 	if (a->local_flags & PFALTQ_FLAG_IF_REMOVED)
@@ -893,9 +895,6 @@ print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
 /*
  * admission control using generalized service curve
  */
-#ifndef INFINITY
-#define	INFINITY	HUGE_VAL  /* positive infinity defined in  */
-#endif
 
 /* add a new service curve to a generalized service curve */
 static void
@@ -1132,8 +1131,6 @@ getifspeed(char *ifname)
 	ifr.ifr_data = (caddr_t)&ifrdat;
 	if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1)
 		err(1, "SIOCGIFDATA");
-	if (shutdown(s, SHUT_RDWR) == -1)
-		err(1, "shutdown");
 	if (close(s))
 		err(1, "close");
 	return ((u_int32_t)ifrdat.ifi_baudrate);
@@ -1158,8 +1155,6 @@ getifmtu(char *ifname)
 #else
 		err(1, "SIOCGIFMTU");
 #endif
-	if (shutdown(s, SHUT_RDWR) == -1)
-		err(1, "shutdown");
 	if (close(s))
 		err(1, "close");
 	if (ifr.ifr_mtu > 0)
diff --git a/contrib/pf/pfctl/pfctl_optimize.c b/contrib/pf/pfctl/pfctl_optimize.c
index 0514e81..9511720 100644
--- a/contrib/pf/pfctl/pfctl_optimize.c
+++ b/contrib/pf/pfctl/pfctl_optimize.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pfctl_optimize.c,v 1.13 2006/10/31 14:17:45 mcbride Exp $ */
+/*	$OpenBSD: pfctl_optimize.c,v 1.17 2008/05/06 03:45:21 mpf Exp $ */
 
 /*
  * Copyright (c) 2004 Mike Frantzen 
@@ -185,7 +185,8 @@ struct pf_rule_field {
     PF_RULE_FIELD(packets,		DC),
     PF_RULE_FIELD(bytes,		DC),
     PF_RULE_FIELD(kif,			DC),
-    PF_RULE_FIELD(states,		DC),
+    PF_RULE_FIELD(states_cur,		DC),
+    PF_RULE_FIELD(states_tot,		DC),
     PF_RULE_FIELD(src_nodes,		DC),
     PF_RULE_FIELD(nr,			DC),
     PF_RULE_FIELD(entries,		DC),
@@ -201,6 +202,7 @@ struct pf_rule_field {
     PF_RULE_FIELD(natpass,		NEVER),
     PF_RULE_FIELD(max_mss,		NEVER),
     PF_RULE_FIELD(min_ttl,		NEVER),
+    PF_RULE_FIELD(set_tos,		NEVER),
 };
 
 
@@ -398,7 +400,7 @@ optimize_superblock(struct pfctl *pf, struct superblock *block)
 	 *     out rules.
 	 */
 
-	/* shortcut.  there will be alot of 1-rule superblocks */
+	/* shortcut.  there will be a lot of 1-rule superblocks */
 	if (!TAILQ_NEXT(TAILQ_FIRST(&block->sb_rules), por_entry))
 		return (0);
 
@@ -1320,8 +1322,9 @@ again:
 
 
 	if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1,
-	    pf->anchor->name, tbl->pt_buf, pf->anchor->ruleset.tticket)) {
-		warn("failed to create table %s", tbl->pt_name);
+	    pf->astack[0]->name, tbl->pt_buf, pf->astack[0]->ruleset.tticket)) {
+		warn("failed to create table %s in %s",
+		    tbl->pt_name, pf->astack[0]->name);
 		return (1);
 	}
 	return (0);
@@ -1424,7 +1427,7 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por)
 		return (0);
 
 	/*
-	 * Have to handle interface groups seperately.  Consider the following
+	 * Have to handle interface groups separately.  Consider the following
 	 * rules:
 	 *	block on EXTIFS to any port 22
 	 *	pass  on em0 to any port 22
diff --git a/contrib/pf/pfctl/pfctl_osfp.c b/contrib/pf/pfctl/pfctl_osfp.c
index 7018d6c..df78981 100644
--- a/contrib/pf/pfctl/pfctl_osfp.c
+++ b/contrib/pf/pfctl/pfctl_osfp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pfctl_osfp.c,v 1.15 2006/12/13 05:10:15 itojun Exp $ */
+/*	$OpenBSD: pfctl_osfp.c,v 1.14 2006/04/08 02:13:14 ray Exp $ */
 
 /*
  * Copyright (c) 2003 Mike Frantzen 
diff --git a/contrib/pf/pfctl/pfctl_parser.c b/contrib/pf/pfctl/pfctl_parser.c
index 7dc0c59..d45b9b7 100644
--- a/contrib/pf/pfctl/pfctl_parser.c
+++ b/contrib/pf/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pfctl_parser.c,v 1.234 2006/10/31 23:46:24 mcbride Exp $ */
+/*	$OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -500,7 +499,7 @@ print_status(struct pf_status *s, int opts)
 	running = s->running ? "Enabled" : "Disabled";
 
 	if (s->since) {
-		unsigned	sec, min, hrs, day = runtime;
+		unsigned int	sec, min, hrs, day = runtime;
 
 		sec = day % 60;
 		day /= 60;
@@ -581,7 +580,11 @@ print_status(struct pf_status *s, int opts)
 		    s->src_nodes, "");
 		for (i = 0; i < SCNT_MAX; i++) {
 			printf("  %-25s %14lld ", pf_scounters[i],
-				   (unsigned long long)s->scounters[i]);
+#ifdef __FreeBSD__
+				    (long long)s->scounters[i]);
+#else
+				    s->scounters[i]);
+#endif
 			if (runtime > 0)
 				printf("%14.1f/s\n",
 				    (double)s->scounters[i] / (double)runtime);
@@ -952,6 +955,12 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
 			printf("sloppy");
 			opts = 0;
 		}
+		if (r->rule_flag & PFRULE_PFLOW) {
+			if (!opts)
+				printf(", ");
+			printf("pflow");
+			opts = 0;
+		}
 		for (i = 0; i < PFTM_MAX; ++i)
 			if (r->timeout[i]) {
 				int j;
@@ -979,6 +988,8 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
 		printf(" min-ttl %d", r->min_ttl);
 	if (r->max_mss)
 		printf(" max-mss %d", r->max_mss);
+	if (r->rule_flag & PFRULE_SET_TOS)
+		printf(" set-tos 0x%2.2x", r->set_tos);
 	if (r->allow_opts)
 		printf(" allow-opts");
 	if (r->action == PF_SCRUB) {
@@ -1007,6 +1018,26 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric)
 	}
 	if (r->rtableid != -1)
 		printf(" rtable %u", r->rtableid);
+	if (r->divert.port) {
+#ifdef __FreeBSD__
+		printf(" divert-to %u", ntohs(r->divert.port));
+#else
+		if (PF_AZERO(&r->divert.addr, r->af)) {
+			printf(" divert-reply");
+		} else {
+			/* XXX cut&paste from print_addr */
+			char buf[48];
+
+			printf(" divert-to ");
+			if (inet_ntop(r->af, &r->divert.addr, buf,
+			    sizeof(buf)) == NULL)
+				printf("?");
+			else
+				printf("%s", buf);
+			printf(" port %u", ntohs(r->divert.port));
+		}
+#endif
+	}
 	if (!anchor_call[0] && (r->action == PF_NAT ||
 	    r->action == PF_BINAT || r->action == PF_RDR)) {
 		printf(" -> ");
@@ -1027,6 +1058,8 @@ print_tabledef(const char *name, int flags, int addrs,
 		printf(" const");
 	if (flags & PFR_TFLAG_PERSIST)
 		printf(" persist");
+	if (flags & PFR_TFLAG_COUNTERS)
+		printf(" counters");
 	SIMPLEQ_FOREACH(ti, nodes, entries) {
 		if (ti->file) {
 			printf(" file \"%s\"", ti->file);
diff --git a/contrib/pf/pfctl/pfctl_parser.h b/contrib/pf/pfctl/pfctl_parser.h
index ab9017e..4560d66 100644
--- a/contrib/pf/pfctl/pfctl_parser.h
+++ b/contrib/pf/pfctl/pfctl_parser.h
@@ -172,10 +172,10 @@ struct node_queue_opt {
 #define	SIMPLEQ_END(head)		NULL
 #define	SIMPLEQ_EMPTY			STAILQ_EMPTY
 #define	SIMPLEQ_NEXT			STAILQ_NEXT
-/*#define SIMPLEQ_FOREACH		STAILQ_FOREACH*/
-#define	SIMPLEQ_FOREACH(var, head, field)	\
-    for((var) = SIMPLEQ_FIRST(head);		\
-	(var) != SIMPLEQ_END(head);		\
+/*#define	SIMPLEQ_FOREACH			STAILQ_FOREACH*/
+#define	SIMPLEQ_FOREACH(var, head, field)		\
+    for((var) = SIMPLEQ_FIRST(head);			\
+	(var) != SIMPLEQ_END(head);			\
 	(var) = SIMPLEQ_NEXT(var, field))
 #define	SIMPLEQ_INIT			STAILQ_INIT
 #define	SIMPLEQ_INSERT_HEAD		STAILQ_INSERT_HEAD
@@ -213,7 +213,7 @@ struct pf_opt_rule {
 
 TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
 
-int	pfctl_rules(int, char *, FILE *, int, int, char *, struct pfr_buffer *);
+int	pfctl_rules(int, char *, int, int, char *, struct pfr_buffer *);
 int	pfctl_optimize_ruleset(struct pfctl *, struct pf_ruleset *);
 
 int	pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
@@ -230,7 +230,7 @@ int	pfctl_set_hostid(struct pfctl *, u_int32_t);
 int	pfctl_set_debug(struct pfctl *, char *);
 int	pfctl_set_interface_flags(struct pfctl *, char *, int, int);
 
-int	parse_rules(FILE *, struct pfctl *);
+int	parse_config(char *, struct pfctl *);
 int	parse_flags(char *);
 int	pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *);
 
diff --git a/contrib/pf/pfctl/pfctl_qstats.c b/contrib/pf/pfctl/pfctl_qstats.c
index d4089d6..95371e4 100644
--- a/contrib/pf/pfctl/pfctl_qstats.c
+++ b/contrib/pf/pfctl/pfctl_qstats.c
@@ -73,7 +73,7 @@ void			 pfctl_insert_altq_node(struct pf_altq_node **,
 struct pf_altq_node	*pfctl_find_altq_node(struct pf_altq_node *,
 			    const char *, const char *);
 void			 pfctl_print_altq_node(int, const struct pf_altq_node *,
-			     unsigned, int);
+			    unsigned, int);
 void			 print_cbqstats(struct queue_stats);
 void			 print_priqstats(struct queue_stats);
 void			 print_hfscstats(struct queue_stats);
@@ -185,8 +185,8 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
 			}
 		}
 #ifdef __FreeBSD__
-		  else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
-		  	memset(&qstats.data, 0, sizeof(qstats.data));
+		else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) {
+			memset(&qstats.data, 0, sizeof(qstats.data));
 			if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
 			    pa.altq.ifname)) != NULL) {
 				memcpy(&node->qstats.data, &qstats.data,
@@ -194,7 +194,7 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root)
 				update_avg(node);
 			} else {
 				pfctl_insert_altq_node(root, pa.altq, qstats);
-			}		
+			}
 		}
 #endif
 	}
@@ -262,8 +262,8 @@ pfctl_find_altq_node(struct pf_altq_node *root, const char *qname,
 }
 
 void
-pfctl_print_altq_node(int dev, const struct pf_altq_node *node, unsigned level,
-    int opts)
+pfctl_print_altq_node(int dev, const struct pf_altq_node *node,
+    unsigned int level, int opts)
 {
 	const struct pf_altq_node	*child;
 
@@ -302,11 +302,11 @@ pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
 {
 	if (a->altq.qid == 0)
 		return;
+
 #ifdef __FreeBSD__
 	if (a->altq.local_flags & PFALTQ_FLAG_IF_REMOVED)
 		return;
 #endif
-
 	switch (a->altq.scheduler) {
 	case ALTQT_CBQ:
 		print_cbqstats(a->qstats);
diff --git a/contrib/pf/pfctl/pfctl_radix.c b/contrib/pf/pfctl/pfctl_radix.c
index 01ad475..38f16c4 100644
--- a/contrib/pf/pfctl/pfctl_radix.c
+++ b/contrib/pf/pfctl/pfctl_radix.c
@@ -30,6 +30,9 @@
  *
  */
 
+#include 
+__FBSDID("$FreeBSD$");
+
 #include 
 #include 
 #include 
@@ -300,29 +303,6 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
 }
 
 int
-pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
-    int *nzero, int flags)
-{
-	struct pfioc_table io;
-
-	if (tbl == NULL || size < 0 || (size && addr == NULL)) {
-		errno = EINVAL;
-		return (-1);
-	}
-	bzero(&io, sizeof io);
-	io.pfrio_flags = flags;
-	io.pfrio_table = *tbl;
-	io.pfrio_buffer = addr;
-	io.pfrio_esize = sizeof(*addr);
-	io.pfrio_size = size;
-	if (ioctl(dev, DIOCRCLRASTATS, &io))
-		return (-1);
-	if (nzero != NULL)
-		*nzero = io.pfrio_nzero;
-	return (0);
-}
-
-int
 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
 {
 	struct pfioc_table io;
@@ -344,32 +324,6 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
 }
 
 int
-pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
-    int *nchange, int *ndel, int flags)
-{
-	struct pfioc_table io;
-
-	if (size < 0 || (size && !tbl)) {
-		errno = EINVAL;
-		return (-1);
-	}
-	bzero(&io, sizeof io);
-	io.pfrio_flags = flags;
-	io.pfrio_buffer = tbl;
-	io.pfrio_esize = sizeof(*tbl);
-	io.pfrio_size = size;
-	io.pfrio_setflag = setflag;
-	io.pfrio_clrflag = clrflag;
-	if (ioctl(dev, DIOCRSETTFLAGS, &io))
-		return (-1);
-	if (nchange)
-		*nchange = io.pfrio_nchange;
-	if (ndel)
-		*ndel = io.pfrio_ndel;
-	return (0);
-}
-
-int
 pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
     int *nmatch, int flags)
 {
diff --git a/contrib/pf/pfctl/pfctl_table.c b/contrib/pf/pfctl/pfctl_table.c
index 3d54466..257c014 100644
--- a/contrib/pf/pfctl/pfctl_table.c
+++ b/contrib/pf/pfctl/pfctl_table.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pfctl_table.c,v 1.66 2007/03/01 17:20:54 deraadt Exp $ */
+/*	$OpenBSD: pfctl_table.c,v 1.67 2008/06/10 20:55:02 mcbride Exp $ */
 
 /*
  * Copyright (c) 2002 Cedric Berger
@@ -275,12 +275,14 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
 			if (b.pfrb_size <= b.pfrb_msize)
 				break;
 		}
-		PFRB_FOREACH(p, &b)
+		PFRB_FOREACH(p, &b) {
+			((struct pfr_astats *)p)->pfras_a.pfra_fback = 0;
 			if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero >
-			     lifetime)
+			    lifetime)
 				if (pfr_buf_add(&b2,
 				    &((struct pfr_astats *)p)->pfras_a))
 					err(1, "duplicate buffer");
+		}
 
 		if (opts & PF_OPT_VERBOSE)
 			flags |= PFR_FLAG_FEEDBACK;
@@ -367,13 +369,14 @@ print_table(struct pfr_table *ta, int verbose, int debug)
 	if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
 		return;
 	if (verbose) {
-		printf("%c%c%c%c%c%c\t%s",
+		printf("%c%c%c%c%c%c%c\t%s",
 		    (ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-',
 		    (ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-',
 		    (ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-',
 		    (ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-',
 		    (ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-',
 		    (ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
+		    (ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-',
 		    ta->pfrt_name);
 		if (ta->pfrt_anchor[0])
 			printf("\t%s", ta->pfrt_anchor);
@@ -428,7 +431,7 @@ void
 print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns)
 {
 	char		ch, buf[256] = "{error}";
-	char		fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y' };
+	char		fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y', ' ' };
 	unsigned int	fback, hostnet;
 
 	fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback;
@@ -477,6 +480,8 @@ print_astats(struct pfr_astats *as, int dns)
 
 	print_addrx(&as->pfras_a, NULL, dns);
 	printf("\tCleared:     %s", ctime(&time));
+ 	if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT)
+		return;
 	for (dir = 0; dir < PFR_DIR_MAX; dir++)
 		for (op = 0; op < PFR_OP_ADDR_MAX; op++)
 			printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n",
diff --git a/contrib/pf/pflogd/pflogd.8 b/contrib/pf/pflogd/pflogd.8
index 22643fc..38c954c 100644
--- a/contrib/pf/pflogd/pflogd.8
+++ b/contrib/pf/pflogd/pflogd.8
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: pflogd.8,v 1.32 2006/12/08 10:26:38 joel Exp $
+.\"	$OpenBSD: pflogd.8,v 1.37 2008/10/22 08:16:49 henning Exp $
 .\"
 .\" Copyright (c) 2001 Can Erkin Acar.  All rights reserved.
 .\"
@@ -26,7 +26,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 9, 2001
+.Dd October 22 2008
 .Dt PFLOGD 8
 .Os
 .Sh NAME
@@ -34,12 +34,14 @@
 .Nd packet filter logging daemon
 .Sh SYNOPSIS
 .Nm pflogd
+.Bk -words
 .Op Fl Dx
 .Op Fl d Ar delay
 .Op Fl f Ar filename
 .Op Fl i Ar interface
 .Op Fl s Ar snaplen
 .Op Ar expression
+.Ek
 .Sh DESCRIPTION
 .Nm
 is a background daemon which reads packets logged by
@@ -94,6 +96,13 @@ or a
 .Dv SIGALRM
 is received.
 .Pp
+.Nm
+will also log the pcap statistics for the
+.Xr pflog 4
+interface to syslog when a
+.Dv SIGUSR1
+is received.
+.Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl D
@@ -116,6 +125,11 @@ By default,
 .Nm
 will use
 .Ar pflog0 .
+Writes a file containing the process ID of the program to
+.Pa /var/run .
+The file name has the form
+The default is
+.Ar pflogd .
 .It Fl s Ar snaplen
 Analyze at most the first
 .Ar snaplen
@@ -204,12 +218,12 @@ the wi0 interface:
 # tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0
 .Ed
 .Sh SEE ALSO
-.Xr tcpdump 1 ,
 .Xr pcap 3 ,
 .Xr pf 4 ,
 .Xr pflog 4 ,
 .Xr pf.conf 5 ,
-.Xr newsyslog 8
+.Xr newsyslog 8 ,
+.Xr tcpdump 1
 .Sh HISTORY
 The
 .Nm
diff --git a/contrib/pf/pflogd/pflogd.c b/contrib/pf/pflogd/pflogd.c
index b470ae1..2fc2338 100644
--- a/contrib/pf/pflogd/pflogd.c
+++ b/contrib/pf/pflogd/pflogd.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pflogd.c,v 1.37 2006/10/26 13:34:47 jmc Exp $	*/
+/*	$OpenBSD: pflogd.c,v 1.46 2008/10/22 08:16:49 henning Exp $	*/
 
 /*
  * Copyright (c) 2001 Theo de Raadt
@@ -37,9 +37,8 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#ifdef __FreeBSD__
-#include 	/* BIOCLOCK */
-#endif
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -48,15 +47,16 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #ifdef __FreeBSD__
+#include 
 #include "pidfile.h"
 #else
 #include 
 #endif
-
 #include "pflogd.h"
 
 pcap_t *hpcap;
@@ -66,7 +66,7 @@ int Debug = 0;
 static int snaplen = DEF_SNAPLEN;
 static int cur_snaplen = DEF_SNAPLEN;
 
-volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup;
+volatile sig_atomic_t gotsig_close, gotsig_alrm, gotsig_hup, gotsig_usr1;
 
 char *filename = PFLOGD_LOG_FILE;
 char *interface = PFLOGD_DEFAULT_IF;
@@ -80,7 +80,9 @@ unsigned int delay = FLUSH_DELAY;
 char *copy_argv(char * const *);
 void  dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
 void  dump_packet_nobuf(u_char *, const struct pcap_pkthdr *, const u_char *);
+void  log_pcap_stats(void);
 int   flush_buffer(FILE *);
+int   if_exists(char *);
 int   init_pcap(void);
 void  logmsg(int, const char *, ...);
 void  purge_buffer(void);
@@ -89,6 +91,7 @@ int   scan_dump(FILE *, off_t);
 int   set_snaplen(int);
 void  set_suspended(int);
 void  sig_alrm(int);
+void  sig_usr1(int);
 void  sig_close(int);
 void  sig_hup(int);
 void  usage(void);
@@ -166,8 +169,8 @@ __dead void
 usage(void)
 {
 	fprintf(stderr, "usage: pflogd [-Dx] [-d delay] [-f filename]");
-	fprintf(stderr, " [-i interface] [-s snaplen]\n");
-	fprintf(stderr, "              [expression]\n");
+	fprintf(stderr, " [-i interface] [-p pidfile]\n");
+	fprintf(stderr, "              [-s snaplen] [expression]\n");
 	exit(1);
 }
 
@@ -190,6 +193,12 @@ sig_alrm(int sig)
 }
 
 void
+sig_usr1(int sig)
+{
+	gotsig_usr1 = 1;
+}
+
+void
 set_pcap_filter(void)
 {
 	struct bpf_program bprog;
@@ -204,6 +213,51 @@ set_pcap_filter(void)
 }
 
 int
+if_exists(char *ifname)
+{
+#ifdef __FreeBSD__
+	struct ifaddrs *ifdata, *mb;
+	int exists = 0;
+
+	getifaddrs(&ifdata);
+        if (ifdata == NULL)
+		return (0);
+
+	for (mb = ifdata; mb != NULL; mb = mb->ifa_next) {
+		if (mb == NULL)
+			continue;
+		if (strlen(ifname) != strlen(mb->ifa_name))
+			continue;
+		if (strncmp(ifname, mb->ifa_name, strlen(ifname)) != 0)
+			continue;
+		exists = 1;
+		break;
+	}
+	freeifaddrs(ifdata);
+
+	return (exists);
+#else
+	int s;
+	struct ifreq ifr;
+	struct if_data ifrdat;
+
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+		err(1, "socket");
+	bzero(&ifr, sizeof(ifr));
+	if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
+		sizeof(ifr.ifr_name))
+			errx(1, "main ifr_name: strlcpy");
+	ifr.ifr_data = (caddr_t)&ifrdat;
+	if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1)
+		return (0);
+	if (close(s))
+		err(1, "close");
+
+	return (1);
+#endif
+}
+
+int
 init_pcap(void)
 {
 	hpcap = pcap_open_live(interface, snaplen, 1, PCAP_TO_MS, errbuf);
@@ -554,10 +608,10 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 		return;
 	}
 
- append:	
+ append:       
 #ifdef __FreeBSD__
- 	sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
- 	sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
+	sh.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
+	sh.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
 	sh.caplen = h->caplen;
 	sh.len = h->len;
 
@@ -575,17 +629,31 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 	return;
 }
 
+void
+log_pcap_stats(void)
+{
+	struct pcap_stat pstat;
+	if (pcap_stats(hpcap, &pstat) < 0)
+		logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
+	else
+		logmsg(LOG_NOTICE,
+			"%u packets received, %u/%u dropped (kernel/pflogd)",
+			pstat.ps_recv, pstat.ps_drop, packets_dropped);
+}
+
 int
 main(int argc, char **argv)
 {
-	struct pcap_stat pstat;
-	int ch, np, Xflag = 0;
+	int ch, np, ret, Xflag = 0;
 	pcap_handler phandler = dump_packet;
 	const char *errstr = NULL;
+	char *pidf = NULL;
+
+	ret = 0;
 
 	closefrom(STDERR_FILENO + 1);
 
-	while ((ch = getopt(argc, argv, "Dxd:f:i:s:")) != -1) {
+	while ((ch = getopt(argc, argv, "Dxd:f:i:p:s:")) != -1) {
 		switch (ch) {
 		case 'D':
 			Debug = 1;
@@ -601,6 +669,9 @@ main(int argc, char **argv)
 		case 'i':
 			interface = optarg;
 			break;
+		case 'p':
+			pidf = optarg;
+			break;
 		case 's':
 			snaplen = strtonum(optarg, 0, PFLOGD_MAXSNAPLEN,
 			    &errstr);
@@ -622,13 +693,21 @@ main(int argc, char **argv)
 	argc -= optind;
 	argv += optind;
 
+	/* does interface exist */
+	if (!if_exists(interface)) {
+		warn("Failed to initialize: %s", interface);
+		logmsg(LOG_ERR, "Failed to initialize: %s", interface);
+		logmsg(LOG_ERR, "Exiting, init failure");
+		exit(1);
+	}
+
 	if (!Debug) {
 		openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
 		if (daemon(0, 0)) {
 			logmsg(LOG_WARNING, "Failed to become daemon: %s",
 			    strerror(errno));
 		}
-		pidfile(NULL);
+		pidfile(pidf);
 	}
 
 	tzset();
@@ -659,6 +738,7 @@ main(int argc, char **argv)
 	signal(SIGINT, sig_close);
 	signal(SIGQUIT, sig_close);
 	signal(SIGALRM, sig_alrm);
+	signal(SIGUSR1, sig_usr1);
 	signal(SIGHUP, sig_hup);
 	alarm(delay);
 
@@ -686,13 +766,12 @@ main(int argc, char **argv)
 		np = pcap_dispatch(hpcap, PCAP_NUM_PKTS,
 		    phandler, (u_char *)dpcap);
 		if (np < 0) {
-#ifdef __FreeBSD__
-			if (errno == ENXIO) {
-				logmsg(LOG_ERR,
-				    "Device not/no longer configured");
+			if (!if_exists(interface) == -1) {
+				logmsg(LOG_NOTICE, "interface %s went away",
+				    interface);
+				ret = -1;
 				break;
 			}
-#endif
 			logmsg(LOG_NOTICE, "%s", pcap_geterr(hpcap));
 		}
 
@@ -715,6 +794,11 @@ main(int argc, char **argv)
 			gotsig_alrm = 0;
 			alarm(delay);
 		}
+
+		if (gotsig_usr1) {
+			log_pcap_stats();
+			gotsig_usr1 = 0;
+		}
 	}
 
 	logmsg(LOG_NOTICE, "Exiting");
@@ -724,15 +808,9 @@ main(int argc, char **argv)
 	}
 	purge_buffer();
 
-	if (pcap_stats(hpcap, &pstat) < 0)
-		logmsg(LOG_WARNING, "Reading stats: %s", pcap_geterr(hpcap));
-	else
-		logmsg(LOG_NOTICE,
-		    "%u packets received, %u/%u dropped (kernel/pflogd)",
-		    pstat.ps_recv, pstat.ps_drop, packets_dropped);
-
+	log_pcap_stats();
 	pcap_close(hpcap);
 	if (!Debug)
 		closelog();
-	return (0);
+	return (ret);
 }
diff --git a/contrib/pf/pflogd/privsep.c b/contrib/pf/pflogd/privsep.c
index a07d141..2e3895d 100644
--- a/contrib/pf/pflogd/privsep.c
+++ b/contrib/pf/pflogd/privsep.c
@@ -23,6 +23,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -31,20 +32,13 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#ifndef __FreeBSD__
 #include 
 #include 
-#endif
 #include 
 #include 
 #include 
 #include 
 #include 
-#ifdef __FreeBSD__
-/* XXX: pcap pollutes namespace with strlcpy if not present previously */
-#include 
-#include 
-#endif
 #include 
 #include 
 #include "pflogd.h"
diff --git a/contrib/pf/pflogd/privsep_fdpass.c b/contrib/pf/pflogd/privsep_fdpass.c
index 50afdfc..0e6c3c4 100644
--- a/contrib/pf/pflogd/privsep_fdpass.c
+++ b/contrib/pf/pflogd/privsep_fdpass.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: privsep_fdpass.c,v 1.2 2004/08/13 02:51:48 djm Exp $	*/
+/*	$OpenBSD: privsep_fdpass.c,v 1.5 2008/03/24 16:11:08 deraadt Exp $	*/
 
 /*
  * Copyright 2001 Niels Provos 
@@ -50,7 +50,10 @@ void
 send_fd(int sock, int fd)
 {
 	struct msghdr msg;
-	char tmp[CMSG_SPACE(sizeof(int))];
+	union {
+		struct cmsghdr hdr;
+		char buf[CMSG_SPACE(sizeof(int))];
+	} cmsgbuf;
 	struct cmsghdr *cmsg;
 	struct iovec vec;
 	int result = 0;
@@ -59,8 +62,8 @@ send_fd(int sock, int fd)
 	memset(&msg, 0, sizeof(msg));
 
 	if (fd >= 0) {
-		msg.msg_control = (caddr_t)tmp;
-		msg.msg_controllen = CMSG_LEN(sizeof(int));
+		msg.msg_control = (caddr_t)&cmsgbuf.buf;
+		msg.msg_controllen = sizeof(cmsgbuf.buf);
 		cmsg = CMSG_FIRSTHDR(&msg);
 		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
 		cmsg->cmsg_level = SOL_SOCKET;
@@ -86,7 +89,10 @@ int
 receive_fd(int sock)
 {
 	struct msghdr msg;
-	char tmp[CMSG_SPACE(sizeof(int))];
+	union {
+		struct cmsghdr hdr;
+		char buf[CMSG_SPACE(sizeof(int))];
+	} cmsgbuf;
 	struct cmsghdr *cmsg;
 	struct iovec vec;
 	ssize_t n;
@@ -98,8 +104,8 @@ receive_fd(int sock)
 	vec.iov_len = sizeof(int);
 	msg.msg_iov = &vec;
 	msg.msg_iovlen = 1;
-	msg.msg_control = tmp;
-	msg.msg_controllen = sizeof(tmp);
+	msg.msg_control = &cmsgbuf.buf;
+	msg.msg_controllen = sizeof(cmsgbuf.buf);
 
 	if ((n = recvmsg(sock, &msg, 0)) == -1)
 		warn("%s: recvmsg", __func__);
diff --git a/sbin/pflogd/Makefile b/sbin/pflogd/Makefile
index ecd06f4..ea37bd1 100644
--- a/sbin/pflogd/Makefile
+++ b/sbin/pflogd/Makefile
@@ -8,7 +8,7 @@ MAN=	pflogd.8
 
 CFLAGS+=-include ${.CURDIR}/../../lib/libpcap/config.h
 
-LDADD=	-lpcap -lutil
+LDADD=	-lpcap
 DPADD=	${LIBPCAP} ${LIBUTIL}
 
 WARNS?=	2
diff --git a/sys/conf/files b/sys/conf/files
index 26c5923..853c0c8 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -386,14 +386,14 @@ contrib/pf/net/pf_if.c		optional pf inet \
 	compile-with "${NORMAL_C} -I$S/contrib/pf"
 contrib/pf/net/pf_ioctl.c	optional pf inet \
 	compile-with "${NORMAL_C} -I$S/contrib/pf"
+contrib/pf/net/pf_lb.c		optional pf inet \
+	compile-with "${NORMAL_C} -I$S/contrib/pf"
 contrib/pf/net/pf_norm.c	optional pf inet \
 	compile-with "${NORMAL_C} -I$S/contrib/pf"
 contrib/pf/net/pf_osfp.c	optional pf inet \
 	compile-with "${NORMAL_C} -I$S/contrib/pf"
 contrib/pf/net/pf_ruleset.c	optional pf inet \
 	compile-with "${NORMAL_C} -I$S/contrib/pf"
-contrib/pf/net/pf_subr.c	optional pf inet \
-	compile-with "${NORMAL_C} -I$S/contrib/pf"
 contrib/pf/net/pf_table.c	optional pf inet \
 	compile-with "${NORMAL_C} -I$S/contrib/pf"
 contrib/pf/netinet/in4_cksum.c	optional pf inet
diff --git a/sys/contrib/altq/altq/altq_red.c b/sys/contrib/altq/altq/altq_red.c
index cd216bd..b461ce0 100644
--- a/sys/contrib/altq/altq/altq_red.c
+++ b/sys/contrib/altq/altq/altq_red.c
@@ -514,11 +514,9 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
 	struct mbuf	*m0;
 	struct pf_mtag	*at;
 	void		*hdr;
-	int		 af;
 
 	at = pf_find_mtag(m);
 	if (at != NULL) {
-		af = at->af;
 		hdr = at->hdr;
 #ifdef ALTQ3_COMPAT
 	} else if (pktattr != NULL) {
@@ -528,9 +526,6 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
 	} else
 		return (0);
 
-	if (af != AF_INET && af != AF_INET6)
-		return (0);
-
 	/* verify that pattr_hdr is within the mbuf data */
 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
 		if (((caddr_t)hdr >= m0->m_data) &&
@@ -541,8 +536,8 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
 		return (0);
 	}
 
-	switch (af) {
-	case AF_INET:
+	switch (((struct ip *)hdr)->ip_v) {
+	case IPVERSION:
 		if (flags & REDF_ECN4) {
 			struct ip *ip = hdr;
 			u_int8_t otos;
@@ -575,7 +570,7 @@ mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
 		}
 		break;
 #ifdef INET6
-	case AF_INET6:
+	case (IPV6_VERSION >> 4):
 		if (flags & REDF_ECN6) {
 			struct ip6_hdr *ip6 = hdr;
 			u_int32_t flowlabel;
diff --git a/sys/contrib/pf/net/if_pflog.c b/sys/contrib/pf/net/if_pflog.c
index d16a09b..0893e8d 100644
--- a/sys/contrib/pf/net/if_pflog.c
+++ b/sys/contrib/pf/net/if_pflog.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: if_pflog.c,v 1.22 2006/12/15 09:31:20 otto Exp $	*/
+/*	$OpenBSD: if_pflog.c,v 1.26 2007/10/18 21:58:18 mpf Exp $	*/
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and 
@@ -99,11 +99,11 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#ifdef INET
 #ifdef __FreeBSD__
+#ifdef INET
 #include 
-#endif
-#endif
+#endif /* INET */
+#endif /* __FreeBSD__ */
 
 #define PFLOGMTU	(32768 + MHLEN + MLEN)
 
@@ -115,7 +115,11 @@ __FBSDID("$FreeBSD$");
 
 void	pflogattach(int);
 int	pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
-    		       struct route *);
+#ifdef __FreeBSD__
+	    struct route *);
+#else
+	    struct rtentry *);
+#endif
 int	pflogioctl(struct ifnet *, u_long, caddr_t);
 void	pflogstart(struct ifnet *);
 #ifdef __FreeBSD__
@@ -128,7 +132,7 @@ int	pflog_clone_destroy(struct ifnet *);
 
 LIST_HEAD(, pflog_softc)	pflogif_list;
 #ifdef __FreeBSD__
-IFC_SIMPLE_DECLARE(pflog, 1);    
+IFC_SIMPLE_DECLARE(pflog, 1);
 #else
 struct if_clone	pflog_cloner =
     IF_CLONE_INITIALIZER("pflog", pflog_clone_create, pflog_clone_destroy);
@@ -136,10 +140,6 @@ struct if_clone	pflog_cloner =
 
 struct ifnet	*pflogifs[PFLOGIFS_MAX];	/* for fast access */
 
-#ifndef __FreeBSD__
-extern int ifqmaxlen;
-#endif
-
 void
 pflogattach(int npflog)
 {
@@ -147,9 +147,6 @@ pflogattach(int npflog)
 	LIST_INIT(&pflogif_list);
 	for (i = 0; i < PFLOGIFS_MAX; i++)
 		pflogifs[i] = NULL;
-#ifndef __FreeBSD__
-	(void) pflog_clone_create(&pflog_cloner, 0);
-#endif
 	if_clone_attach(&pflog_cloner);
 }
 
@@ -168,9 +165,9 @@ pflog_clone_create(struct if_clone *ifc, int unit)
 	if (unit >= PFLOGIFS_MAX)
 		return (EINVAL);
 
-	if ((pflogif = malloc(sizeof(*pflogif), M_DEVBUF, M_NOWAIT)) == NULL)
+	if ((pflogif = malloc(sizeof(*pflogif),
+	    M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
 		return (ENOMEM);
-	bzero(pflogif, sizeof(*pflogif));
 
 	pflogif->sc_unit = unit;
 #ifdef __FreeBSD__
@@ -209,6 +206,7 @@ pflog_clone_create(struct if_clone *ifc, int unit)
 
 	s = splnet();
 #ifdef __FreeBSD__
+	/* XXX: Why pf(4) lock?! Better add a pflog lock?! */
 	PF_LOCK();
 #endif
 	LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list);
@@ -289,7 +287,11 @@ pflogstart(struct ifnet *ifp)
 
 int
 pflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
-       struct route *ro)
+#ifdef __FreeBSD__
+	struct route *rt)
+#else
+	struct rtentry *rt)
+#endif
 {
 	m_freem(m);
 	return (0);
@@ -300,9 +302,6 @@ int
 pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
 	switch (cmd) {
-	case SIOCSIFADDR:
-	case SIOCAIFADDR:
-	case SIOCSIFDSTADDR:
 	case SIOCSIFFLAGS:
 #ifdef __FreeBSD__
 		if (ifp->if_flags & IFF_UP)
@@ -317,7 +316,7 @@ pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 #endif
 		break;
 	default:
-		return (EINVAL);
+		return (ENOTTY);
 	}
 
 	return (0);
@@ -333,7 +332,7 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
 	struct pfloghdr hdr;
 
 	if (kif == NULL || m == NULL || rm == NULL || pd == NULL)
-		return (-1);
+		return ( 1);
 
 	if ((ifn = pflogifs[rm->logif]) == NULL || !ifn->if_bpf)
 		return (0);
@@ -347,7 +346,7 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
 
 	if (am == NULL) {
 		hdr.rulenr = htonl(rm->nr);
-		hdr.subrulenr = -1;
+		hdr.subrulenr =  1;
 	} else {
 		hdr.rulenr = htonl(am->nr);
 		hdr.subrulenr = htonl(rm->nr);
@@ -357,11 +356,11 @@ pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
 	}
 	if (rm->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done)
 #ifdef __FreeBSD__
-		/* 
+		/*
 		 * XXX: This should not happen as we force an early lookup
 		 * via debug.pfugidhack
 		 */
-		 ; /* empty */
+		; /* empty */
 #else
 		pd->lookup.done = pf_socket_lookup(dir, pd);
 #endif
diff --git a/sys/contrib/pf/net/if_pflog.h b/sys/contrib/pf/net/if_pflog.h
index a3c74d1..5f48f6c 100644
--- a/sys/contrib/pf/net/if_pflog.h
+++ b/sys/contrib/pf/net/if_pflog.h
@@ -1,5 +1,4 @@
-/* $FreeBSD$ */
-/* $OpenBSD: if_pflog.h,v 1.14 2006/10/25 11:27:01 henning Exp $ */
+/* $OpenBSD: if_pflog.h,v 1.13 2006/10/23 12:46:09 henning Exp $ */
 /*
  * Copyright 2001 Niels Provos 
  * All rights reserved.
@@ -26,11 +25,10 @@
  */
 
 #ifndef _NET_IF_PFLOG_H_
-#define _NET_IF_PFLOG_H_
+#define	_NET_IF_PFLOG_H_
 
 #define	PFLOGIFS_MAX	16
 
-#ifdef _KERNEL
 struct pflog_softc {
 #ifdef __FreeBSD__
 	struct ifnet		*sc_ifp;	/* the interface pointer */
@@ -40,9 +38,8 @@ struct pflog_softc {
 	int			sc_unit;
 	LIST_ENTRY(pflog_softc)	sc_list;
 };
-#endif /* _KERNEL */
 
-#define PFLOG_RULESET_NAME_SIZE	16
+#define	PFLOG_RULESET_NAME_SIZE	16
 
 struct pfloghdr {
 	u_int8_t	length;
@@ -61,9 +58,9 @@ struct pfloghdr {
 	u_int8_t	pad[3];
 };
 
-#define PFLOG_HDRLEN		sizeof(struct pfloghdr)
+#define	PFLOG_HDRLEN		sizeof(struct pfloghdr)
 /* minus pad, also used as a signature */
-#define PFLOG_REAL_HDRLEN	offsetof(struct pfloghdr, pad)
+#define	PFLOG_REAL_HDRLEN	offsetof(struct pfloghdr, pad)
 
 /* XXX remove later when old format logs are no longer needed */
 struct old_pfloghdr {
@@ -74,23 +71,24 @@ struct old_pfloghdr {
 	u_short action;
 	u_short dir;
 };
-#define OLD_PFLOG_HDRLEN	sizeof(struct old_pfloghdr)
+#define	OLD_PFLOG_HDRLEN	sizeof(struct old_pfloghdr)
 
 #ifdef _KERNEL
-
 #ifdef __FreeBSD__
 struct pf_rule;
 struct pf_ruleset;
 struct pfi_kif;
 struct pf_pdesc;
 
+#if 0
 typedef int pflog_packet_t(struct pfi_kif *, struct mbuf *, sa_family_t,
     u_int8_t, u_int8_t, struct pf_rule *, struct pf_rule *,
     struct pf_ruleset *, struct pf_pdesc *);
 extern pflog_packet_t *pflog_packet_ptr;
-#define	PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) do {	\
-	if (pflog_packet_ptr != NULL)		\
-	pflog_packet_ptr(i,a,b,c,d,e,f,g,h);	\
+#endif
+#define	PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) do {		\
+	if (pflog_packet_ptr != NULL)			\
+		pflog_packet_ptr(i,a,b,c,d,e,f,g,h);    \
 } while (0)
 #else /* ! __FreeBSD__ */
 #if NPFLOG > 0
@@ -98,6 +96,6 @@ extern pflog_packet_t *pflog_packet_ptr;
 #else
 #define	PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) ((void)0)
 #endif /* NPFLOG > 0 */
-#endif /* __FreeBSD__ */
+#endif
 #endif /* _KERNEL */
 #endif /* _NET_IF_PFLOG_H_ */
diff --git a/sys/contrib/pf/net/if_pflow.h b/sys/contrib/pf/net/if_pflow.h
new file mode 100644
index 0000000..35ccbeb
--- /dev/null
+++ b/sys/contrib/pf/net/if_pflow.h
@@ -0,0 +1,126 @@
+/*	$OpenBSD: if_pflow.h,v 1.5 2009/02/27 11:09:36 gollo Exp $	*/
+
+/*
+ * Copyright (c) 2008 Henning Brauer 
+ * Copyright (c) 2008 Joerg Goltermann 
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NET_IF_PFLOW_H_
+#define	_NET_IF_PFLOW_H_
+
+#define	PFLOW_ID_LEN	sizeof(u_int64_t)
+
+#define	PFLOW_MAXFLOWS 30
+#define	PFLOW_VERSION 5
+#define	PFLOW_ENGINE_TYPE 42
+#define	PFLOW_ENGINE_ID 42
+#define	PFLOW_MAXBYTES 0xffffffff
+#define	PFLOW_TIMEOUT 30
+
+struct pflow_flow {
+	u_int32_t	src_ip;
+	u_int32_t	dest_ip;
+	u_int32_t	nexthop_ip;
+	u_int16_t	if_index_in;
+	u_int16_t	if_index_out;
+	u_int32_t	flow_packets;
+	u_int32_t	flow_octets;
+	u_int32_t	flow_start;
+	u_int32_t	flow_finish;
+	u_int16_t	src_port;
+	u_int16_t	dest_port;
+	u_int8_t	pad1;
+	u_int8_t	tcp_flags;
+	u_int8_t	protocol;
+	u_int8_t	tos;
+	u_int16_t	src_as;
+	u_int16_t	dest_as;
+	u_int8_t	src_mask;
+	u_int8_t	dest_mask;
+	u_int16_t	pad2;
+} __packed;
+
+#ifdef _KERNEL
+
+extern int pflow_ok;
+
+struct pflow_softc {
+	struct ifnet		 sc_if;
+	struct ifnet		*sc_pflow_ifp;
+
+	unsigned int		 sc_count;
+	unsigned int		 sc_maxcount;
+	u_int64_t		 sc_gcounter;
+	struct ip_moptions	 sc_imo;
+#ifdef __FreeBSD__
+	struct callout		 sc_tmo;
+#else
+	struct timeout		 sc_tmo;
+#endif
+	struct in_addr		 sc_sender_ip;
+	u_int16_t		 sc_sender_port;
+	struct in_addr		 sc_receiver_ip;
+	u_int16_t		 sc_receiver_port;
+	struct mbuf		*sc_mbuf;	/* current cumulative mbuf */
+	SLIST_ENTRY(pflow_softc) sc_next;
+};
+
+extern struct pflow_softc	*pflowif;
+
+#endif /* _KERNEL */
+
+struct pflow_header {
+	u_int16_t	version;
+	u_int16_t	count;
+	u_int32_t	uptime_ms;
+	u_int32_t	time_sec;
+	u_int32_t	time_nanosec;
+	u_int32_t	flow_sequence;
+	u_int8_t	engine_type;
+	u_int8_t	engine_id;
+	u_int8_t	reserved1;
+	u_int8_t	reserved2;
+} __packed;
+
+#define	PFLOW_HDRLEN sizeof(struct pflow_header)
+
+struct pflowstats {
+	u_int64_t	pflow_flows;
+	u_int64_t	pflow_packets;
+	u_int64_t	pflow_onomem;
+	u_int64_t	pflow_oerrors;
+};
+
+/*
+ * Configuration structure for SIOCSETPFLOW SIOCGETPFLOW
+ */
+struct pflowreq {
+	struct in_addr		sender_ip;
+	struct in_addr		receiver_ip;
+	u_int16_t		receiver_port;
+	u_int16_t		addrmask;
+#define	PFLOW_MASK_SRCIP	0x01
+#define	PFLOW_MASK_DSTIP	0x02
+#define	PFLOW_MASK_DSTPRT	0x04
+};
+
+#ifdef _KERNEL
+int export_pflow(struct pf_state *);
+int pflow_sysctl(int *, u_int,  void *, size_t *, void *, size_t);
+#endif /* _KERNEL */
+
+#endif /* _NET_IF_PFLOW_H_ */
diff --git a/sys/contrib/pf/net/if_pfsync.c b/sys/contrib/pf/net/if_pfsync.c
index 9466118..ba8a348 100644
--- a/sys/contrib/pf/net/if_pfsync.c
+++ b/sys/contrib/pf/net/if_pfsync.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: if_pfsync.c,v 1.73 2006/11/16 13:13:38 henning Exp $	*/
+/*	$OpenBSD: if_pfsync.c,v 1.110 2009/02/24 05:39:19 dlg Exp $	*/
 
 /*
  * Copyright (c) 2002 Michael Shalayeff
@@ -26,10 +26,25 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * Copyright (c) 2009 David Gwynne 
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
 #ifdef __FreeBSD__
 #include "opt_inet.h"
 #include "opt_inet6.h"
-#include "opt_carp.h"
 #include "opt_bpf.h"
 #include "opt_pf.h"
 
@@ -56,7 +71,10 @@ __FBSDID("$FreeBSD$");
 #endif /* __FreeBSD__ */
 
 #include 
+#include 
 #ifdef __FreeBSD__
+#include 
+#include 
 #include 
 #endif
 #include 
@@ -72,12 +90,14 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
 #else
 #include 
 #include 
 #endif
-#include 
+#include 
+#ifndef __FreeBSD__
+#include 
+#endif
 
 #include 
 #ifdef __FreeBSD__
@@ -86,6 +106,11 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#include 
+#ifdef __FreeBSD__
+#include 
+#endif
+
 #include 
 #include 
 #include 
@@ -117,23 +142,191 @@ __FBSDID("$FreeBSD$");
 #include "pfsync.h"
 #endif
 
-#define PFSYNC_MINMTU	\
-    (sizeof(struct pfsync_header) + sizeof(struct pf_state))
+#define PFSYNC_MINPKT ( \
+	sizeof(struct ip) + \
+	sizeof(struct pfsync_header) + \
+	sizeof(struct pfsync_subheader) + \
+	sizeof(struct pfsync_eof))
+
+struct pfsync_pkt {
+	struct ip *ip;
+	struct in_addr src;
+	u_int8_t flags;
+};
+
+int	pfsync_input_hmac(struct mbuf *, int);
+
+int	pfsync_upd_tcp(struct pf_state *, struct pfsync_state_peer *,
+	    struct pfsync_state_peer *);
+
+int	pfsync_in_clr(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_ins(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_iack(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_upd(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_upd_c(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_ureq(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_del(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_del_c(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_bus(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_tdb(struct pfsync_pkt *, struct mbuf *, int, int);
+int	pfsync_in_eof(struct pfsync_pkt *, struct mbuf *, int, int);
+
+int	pfsync_in_error(struct pfsync_pkt *, struct mbuf *, int, int);
+
+int	(*pfsync_acts[])(struct pfsync_pkt *, struct mbuf *, int, int) = {
+	pfsync_in_clr,			/* PFSYNC_ACT_CLR */
+	pfsync_in_ins,			/* PFSYNC_ACT_INS */
+	pfsync_in_iack,			/* PFSYNC_ACT_INS_ACK */
+	pfsync_in_upd,			/* PFSYNC_ACT_UPD */
+	pfsync_in_upd_c,		/* PFSYNC_ACT_UPD_C */
+	pfsync_in_ureq,			/* PFSYNC_ACT_UPD_REQ */
+	pfsync_in_del,			/* PFSYNC_ACT_DEL */
+	pfsync_in_del_c,		/* PFSYNC_ACT_DEL_C */
+	pfsync_in_error,		/* PFSYNC_ACT_INS_F */
+	pfsync_in_error,		/* PFSYNC_ACT_DEL_F */
+	pfsync_in_bus,			/* PFSYNC_ACT_BUS */
+	pfsync_in_tdb,			/* PFSYNC_ACT_TDB */
+	pfsync_in_eof			/* PFSYNC_ACT_EOF */
+};
+
+struct pfsync_q {
+	int		(*write)(struct pf_state *, struct mbuf *, int);
+	size_t		len;
+	u_int8_t	action;
+};
+
+/* we have one of these for every PFSYNC_S_ */
+int	pfsync_out_state(struct pf_state *, struct mbuf *, int);
+int	pfsync_out_iack(struct pf_state *, struct mbuf *, int);
+int	pfsync_out_upd_c(struct pf_state *, struct mbuf *, int);
+int	pfsync_out_del(struct pf_state *, struct mbuf *, int);
+
+struct pfsync_q pfsync_qs[] = {
+	{ pfsync_out_state, sizeof(struct pfsync_state),   PFSYNC_ACT_INS },
+	{ pfsync_out_iack,  sizeof(struct pfsync_ins_ack), PFSYNC_ACT_INS_ACK },
+	{ pfsync_out_state, sizeof(struct pfsync_state),   PFSYNC_ACT_UPD },
+	{ pfsync_out_upd_c, sizeof(struct pfsync_upd_c),   PFSYNC_ACT_UPD_C },
+	{ pfsync_out_del,   sizeof(struct pfsync_del_c),   PFSYNC_ACT_DEL_C }
+};
+
+void	pfsync_q_ins(struct pf_state *, int);
+void	pfsync_q_del(struct pf_state *);
+
+struct pfsync_upd_req_item {
+	TAILQ_ENTRY(pfsync_upd_req_item)	ur_entry;
+	struct pfsync_upd_req			ur_msg;
+};
+TAILQ_HEAD(pfsync_upd_reqs, pfsync_upd_req_item);
+
+struct pfsync_deferral {
+	TAILQ_ENTRY(pfsync_deferral)		 pd_entry;
+	struct pf_state				*pd_st;
+	struct mbuf				*pd_m;
+#ifdef __FreeBSD__
+	struct callout				 pd_tmo;
+#else
+	struct timeout				 pd_tmo;
+#endif
+};
+TAILQ_HEAD(pfsync_deferrals, pfsync_deferral);
+
+#define PFSYNC_PLSIZE	MAX(sizeof(struct pfsync_upd_req_item), \
+			    sizeof(struct pfsync_deferral))
+
+#ifdef notyet
+int	pfsync_out_tdb(struct tdb *, struct mbuf *, int);
+#endif
+
+struct pfsync_softc {
+#ifdef __FreeBSD__
+	struct ifnet		*sc_ifp;
+#else
+	struct ifnet		 sc_if;
+#endif
+	struct ifnet		*sc_sync_if;
+
+#ifdef __FreeBSD__
+	uma_zone_t		 sc_pool;
+#else
+	struct pool		 sc_pool;
+#endif
+
+	struct ip_moptions	 sc_imo;
+
+	struct in_addr		 sc_sync_peer;
+	u_int8_t		 sc_maxupdates;
+#ifdef __FreeBSD__
+	int			 pfsync_sync_ok;
+#endif
+
+	struct ip		 sc_template;
 
-#ifdef PFSYNCDEBUG
-#define DPRINTF(x)    do { if (pfsyncdebug) printf x ; } while (0)
-int pfsyncdebug;
+	struct pf_state_queue	 sc_qs[PFSYNC_S_COUNT];
+	size_t			 sc_len;
+
+	struct pfsync_upd_reqs	 sc_upd_req_list;
+
+	struct pfsync_deferrals	 sc_deferrals;
+	u_int			 sc_deferred;
+
+	void			*sc_plus;
+	size_t			 sc_pluslen;
+
+	u_int32_t		 sc_ureq_sent;
+	int			 sc_bulk_tries;
+#ifdef __FreeBSD__
+	struct callout		 sc_bulkfail_tmo;
+#else
+	struct timeout		 sc_bulkfail_tmo;
+#endif
+
+	u_int32_t		 sc_ureq_received;
+	struct pf_state		*sc_bulk_next;
+	struct pf_state		*sc_bulk_last;
+#ifdef __FreeBSD__
+	struct callout		 sc_bulk_tmo;
+#else
+	struct timeout		 sc_bulk_tmo;
+#endif
+
+	TAILQ_HEAD(, tdb)	 sc_tdb_q;
+
+#ifdef __FreeBSD__
+	struct callout		 sc_tmo;
 #else
-#define DPRINTF(x)
+	struct timeout		 sc_tmo;
+#endif
+#ifdef __FreeBSD__
+	eventhandler_tag	 sc_detachtag;
 #endif
 
+};
+
+#ifdef __FreeBSD__
+static VNET_DEFINE(struct pfsync_softc	*, pfsyncif) = NULL;
+#define	V_pfsyncif		VNET(pfsyncif)
+
+static VNET_DEFINE(struct pfsyncstats, pfsyncstats);
+#define	V_pfsyncstats		VNET(pfsyncstats)
+
+SYSCTL_NODE(_net, OID_AUTO, pfsync, CTLFLAG_RW, 0, "PFSYNC");
+SYSCTL_VNET_STRUCT(_net_pfsync, OID_AUTO, stats, CTLFLAG_RW,
+    &VNET_NAME(pfsyncstats), pfsyncstats,
+    "PFSYNC statistics (struct pfsyncstats, net/if_pfsync.h)");
+#else
 struct pfsync_softc	*pfsyncif = NULL;
 struct pfsyncstats	 pfsyncstats;
+#define	V_pfsyncstats	 pfsyncstats
+#endif
+
 #ifdef __FreeBSD__
-SYSCTL_DECL(_net_inet_pfsync);
-SYSCTL_STRUCT(_net_inet_pfsync, 0, stats, CTLFLAG_RW,
-    &pfsyncstats, pfsyncstats,
-    "PFSYNC statistics (struct pfsyncstats, net/if_pfsync.h)");
+static void	pfsyncintr(void *);
+struct pfsync_swi {
+	void *	pfsync_swi_cookie;
+};
+static struct pfsync_swi	 pfsync_swi;
+#define	schednetisr(p)	swi_sched(pfsync_swi.pfsync_swi_cookie, 0)
+#define	NETISR_PFSYNC
 #endif
 
 void	pfsyncattach(int);
@@ -144,45 +337,53 @@ void	pfsync_clone_destroy(struct ifnet *);
 int	pfsync_clone_create(struct if_clone *, int);
 int	pfsync_clone_destroy(struct ifnet *);
 #endif
-void	pfsync_setmtu(struct pfsync_softc *, int);
 int	pfsync_alloc_scrub_memory(struct pfsync_state_peer *,
 	    struct pf_state_peer *);
-int	pfsync_insert_net_state(struct pfsync_state *, u_int8_t);
-#ifdef PFSYNC_TDB
 void	pfsync_update_net_tdb(struct pfsync_tdb *);
-#endif
 int	pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
+#ifdef __FreeBSD__
 	    struct route *);
+#else
+	    struct rtentry *);
+#endif
 int	pfsyncioctl(struct ifnet *, u_long, caddr_t);
 void	pfsyncstart(struct ifnet *);
 
-struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
-int	pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
-int	pfsync_sendout(struct pfsync_softc *);
-#ifdef PFSYNC_TDB
+struct mbuf *pfsync_if_dequeue(struct ifnet *);
+struct mbuf *pfsync_get_mbuf(struct pfsync_softc *);
+
+void	pfsync_deferred(struct pf_state *, int);
+void	pfsync_undefer(struct pfsync_deferral *, int);
+void	pfsync_defer_tmo(void *);
+
+void	pfsync_request_update(u_int32_t, u_int64_t);
+void	pfsync_update_state_req(struct pf_state *);
+
+void	pfsync_drop(struct pfsync_softc *);
+void	pfsync_sendout(void);
+void	pfsync_send_plus(void *, size_t);
 int	pfsync_tdb_sendout(struct pfsync_softc *);
-#endif
 int	pfsync_sendout_mbuf(struct pfsync_softc *, struct mbuf *);
 void	pfsync_timeout(void *);
-#ifdef PFSYNC_TDB
 void	pfsync_tdb_timeout(void *);
-#endif
 void	pfsync_send_bus(struct pfsync_softc *, u_int8_t);
+
+void	pfsync_bulk_start(void);
+void	pfsync_bulk_status(u_int8_t);
 void	pfsync_bulk_update(void *);
-void	pfsync_bulkfail(void *);
+void	pfsync_bulk_fail(void *);
 
 #ifdef __FreeBSD__
 void	pfsync_ifdetach(void *, struct ifnet *);
-void	pfsync_senddef(void *, int);
 
 /* XXX: ugly */
 #define	betoh64		(unsigned long long)be64toh
 #define	timeout_del	callout_stop
 #endif
 
-int	pfsync_sync_ok;
+#define PFSYNC_MAX_BULKTRIES	12
 #ifndef __FreeBSD__
-extern int ifqmaxlen;
+int	pfsync_sync_ok;
 #endif
 
 #ifdef __FreeBSD__
@@ -197,7 +398,6 @@ pfsyncattach(int npfsync)
 {
 	if_clone_attach(&pfsync_cloner);
 }
-
 int
 #ifdef __FreeBSD__
 pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param)
@@ -205,95 +405,103 @@ pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param)
 pfsync_clone_create(struct if_clone *ifc, int unit)
 #endif
 {
+	struct pfsync_softc *sc;
 	struct ifnet *ifp;
+	int q;
 
 	if (unit != 0)
 		return (EINVAL);
 
+#ifndef __FreeBSD__
 	pfsync_sync_ok = 1;
-	if ((pfsyncif = malloc(sizeof(*pfsyncif), M_DEVBUF, M_NOWAIT)) == NULL)
+#endif
+
+	sc = malloc(sizeof(struct pfsync_softc), M_DEVBUF, M_NOWAIT | M_ZERO);
+	if (sc == NULL)
 		return (ENOMEM);
-	bzero(pfsyncif, sizeof(*pfsyncif));
+
+	for (q = 0; q < PFSYNC_S_COUNT; q++)
+		TAILQ_INIT(&sc->sc_qs[q]);
+
 #ifdef __FreeBSD__
-	if ((pfsyncif->sc_imo.imo_membership = (struct in_multi **)malloc(
-	    (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_DEVBUF,
-	    M_NOWAIT)) == NULL) {
-		free(pfsyncif, M_DEVBUF);
-		return (ENOSPC);
+	sc->pfsync_sync_ok = 1;
+	sc->sc_pool = uma_zcreate("pfsync", PFSYNC_PLSIZE,
+			NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+	if (sc->sc_pool == NULL) {
+		free(sc, M_DEVBUF);
+		return (ENOMEM);
 	}
-	pfsyncif->sc_imo.imo_mfilters = NULL;
-	pfsyncif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
-	pfsyncif->sc_imo.imo_multicast_vif = -1;
+#else
+	pool_init(&sc->sc_pool, PFSYNC_PLSIZE, 0, 0, 0, "pfsync", NULL);
+#endif
+	TAILQ_INIT(&sc->sc_upd_req_list);
+	TAILQ_INIT(&sc->sc_deferrals);
+	sc->sc_deferred = 0;
+
+	TAILQ_INIT(&sc->sc_tdb_q);
+
+	sc->sc_len = PFSYNC_MINPKT;
+	sc->sc_maxupdates = 128;
+
+#ifdef __FreeBSD__
+	sc->sc_imo.imo_membership = (struct in_multi **)malloc(
+	    (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_DEVBUF,
+	    M_NOWAIT | M_ZERO);
+	sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
+	sc->sc_imo.imo_multicast_vif = -1;
+#else
+	sc->sc_imo.imo_membership = (struct in_multi **)malloc(
+	    (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS,
+	    M_WAITOK | M_ZERO);
+	sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
+#endif
 
-	ifp = pfsyncif->sc_ifp = if_alloc(IFT_PFSYNC);
+#ifdef __FreeBSD__
+	ifp = sc->sc_ifp = if_alloc(IFT_PFSYNC);
 	if (ifp == NULL) {
-		free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
-		free(pfsyncif, M_DEVBUF);
+		free(sc->sc_imo.imo_membership, M_DEVBUF);
+		uma_zdestroy(sc->sc_pool);
+		free(sc, M_DEVBUF);
 		return (ENOSPC);
 	}
 	if_initname(ifp, ifc->ifc_name, unit);
 
-	pfsyncif->sc_detachtag = EVENTHANDLER_REGISTER(ifnet_departure_event,
+	sc->sc_detachtag = EVENTHANDLER_REGISTER(ifnet_departure_event,
+#ifdef __FreeBSD__
+	    pfsync_ifdetach, V_pfsyncif, EVENTHANDLER_PRI_ANY);
+#else
 	    pfsync_ifdetach, pfsyncif, EVENTHANDLER_PRI_ANY);
-	if (pfsyncif->sc_detachtag == NULL) {
+#endif
+	if (sc->sc_detachtag == NULL) {
 		if_free(ifp);
-		free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
-		free(pfsyncif, M_DEVBUF);
+		free(sc->sc_imo.imo_membership, M_DEVBUF);
+		uma_zdestroy(sc->sc_pool);
+		free(sc, M_DEVBUF);
 		return (ENOSPC);
 	}
-
-	pfsyncif->sc_ifq.ifq_maxlen = ifqmaxlen;
-	mtx_init(&pfsyncif->sc_ifq.ifq_mtx, ifp->if_xname,
-	    "pfsync send queue", MTX_DEF);
-	TASK_INIT(&pfsyncif->sc_send_task, 0, pfsync_senddef, pfsyncif);
-#endif
-	pfsyncif->sc_mbuf = NULL;
-	pfsyncif->sc_mbuf_net = NULL;
-#ifdef PFSYNC_TDB
-	pfsyncif->sc_mbuf_tdb = NULL;
-#endif
-	pfsyncif->sc_statep.s = NULL;
-	pfsyncif->sc_statep_net.s = NULL;
-#ifdef PFSYNC_TDB
-	pfsyncif->sc_statep_tdb.t = NULL;
-#endif
-	pfsyncif->sc_maxupdates = 128;
-#ifdef __FreeBSD__
-	pfsyncif->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP);
-	pfsyncif->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP);
 #else
-	pfsyncif->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
-	pfsyncif->sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
-#endif
-	pfsyncif->sc_ureq_received = 0;
-	pfsyncif->sc_ureq_sent = 0;
-	pfsyncif->sc_bulk_send_next = NULL;
-	pfsyncif->sc_bulk_terminator = NULL;
-#ifndef __FreeBSD__
-	ifp = &pfsyncif->sc_if;
+	ifp = &sc->sc_if;
 	snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit);
 #endif
-	ifp->if_softc = pfsyncif;
+	ifp->if_softc = sc;
 	ifp->if_ioctl = pfsyncioctl;
 	ifp->if_output = pfsyncoutput;
 	ifp->if_start = pfsyncstart;
 	ifp->if_type = IFT_PFSYNC;
 	ifp->if_snd.ifq_maxlen = ifqmaxlen;
-	ifp->if_hdrlen = PFSYNC_HDRLEN;
-	pfsync_setmtu(pfsyncif, ETHERMTU);
+	ifp->if_hdrlen = sizeof(struct pfsync_header);
+	ifp->if_mtu = 1500; /* XXX */
 #ifdef __FreeBSD__
-	callout_init(&pfsyncif->sc_tmo, CALLOUT_MPSAFE);
-#ifdef PFSYNC_TDB
-	callout_init(&pfsyncif->sc_tdb_tmo, CALLOUT_MPSAFE);
-#endif
-	callout_init(&pfsyncif->sc_bulk_tmo, CALLOUT_MPSAFE);
-	callout_init(&pfsyncif->sc_bulkfail_tmo, CALLOUT_MPSAFE);
+	callout_init(&sc->sc_tmo, CALLOUT_MPSAFE);
+	callout_init(&sc->sc_bulk_tmo, CALLOUT_MPSAFE);
+	callout_init(&sc->sc_bulkfail_tmo, CALLOUT_MPSAFE);
 #else
-	timeout_set(&pfsyncif->sc_tmo, pfsync_timeout, pfsyncif);
-	timeout_set(&pfsyncif->sc_tdb_tmo, pfsync_tdb_timeout, pfsyncif);
-	timeout_set(&pfsyncif->sc_bulk_tmo, pfsync_bulk_update, pfsyncif);
-	timeout_set(&pfsyncif->sc_bulkfail_tmo, pfsync_bulkfail, pfsyncif);
+	ifp->if_hardmtu = MCLBYTES; /* XXX */
+	timeout_set(&sc->sc_tmo, pfsync_timeout, sc);
+	timeout_set(&sc->sc_bulk_tmo, pfsync_bulk_update, sc);
+	timeout_set(&sc->sc_bulkfail_tmo, pfsync_bulk_fail, sc);
 #endif
+
 	if_attach(ifp);
 #ifndef __FreeBSD__
 	if_alloc_sadl(ifp);
@@ -307,10 +515,16 @@ pfsync_clone_create(struct if_clone *ifc, int unit)
 #ifdef __FreeBSD__
 	bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
 #else
-	bpfattach(&pfsyncif->sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
+	bpfattach(&sc->sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
 #endif
 #endif
 
+#ifdef __FreeBSD__
+	V_pfsyncif = sc;
+#else
+	pfsyncif = sc;
+#endif
+
 	return (0);
 }
 
@@ -321,60 +535,92 @@ int
 #endif
 pfsync_clone_destroy(struct ifnet *ifp)
 {
+	struct pfsync_softc *sc = ifp->if_softc;
+
+#ifdef __FreeBSD__
+	EVENTHANDLER_DEREGISTER(ifnet_departure_event, sc->sc_detachtag);
+#endif
+	timeout_del(&sc->sc_bulk_tmo);
+	timeout_del(&sc->sc_tmo);
+#if NCARP > 0
+#ifdef notyet
 #ifdef __FreeBSD__
-	EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfsyncif->sc_detachtag);
-	callout_stop(&pfsyncif->sc_tmo);
-#ifdef PFSYNC_TDB
-	callout_stop(&pfsyncif->sc_tdb_tmo);
+	if (!sc->pfsync_sync_ok)
+#else
+	if (!pfsync_sync_ok)
+#endif
+		carp_group_demote_adj(&sc->sc_if, -1);
 #endif
-	callout_stop(&pfsyncif->sc_bulk_tmo);
-	callout_stop(&pfsyncif->sc_bulkfail_tmo);
-	/* XXX: more? */
 #endif
-
 #if NBPFILTER > 0
 	bpfdetach(ifp);
 #endif
 	if_detach(ifp);
+
+	pfsync_drop(sc);
+
+	while (sc->sc_deferred > 0)
+		pfsync_undefer(TAILQ_FIRST(&sc->sc_deferrals), 0);
+
+#ifdef __FreeBSD__
+	UMA_DESTROY(sc->sc_pool);
+#else
+	pool_destroy(&sc->sc_pool);
+#endif
 #ifdef __FreeBSD__
 	if_free(ifp);
-	free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
+	free(sc->sc_imo.imo_membership, M_DEVBUF);
+#else
+	free(sc->sc_imo.imo_membership, M_IPMOPTS);
 #endif
-	free(pfsyncif, M_DEVBUF);
+	free(sc, M_DEVBUF);
+
+#ifdef __FreeBSD__
+	V_pfsyncif = NULL;
+#else
 	pfsyncif = NULL;
+#endif
+
 #ifndef __FreeBSD__
 	return (0);
 #endif
 }
 
-/*
- * Start output on the pfsync interface.
- */
-void
-pfsyncstart(struct ifnet *ifp)
+struct mbuf *
+pfsync_if_dequeue(struct ifnet *ifp)
 {
 	struct mbuf *m;
 #ifndef __FreeBSD__
 	int s;
 #endif
 
-	for (;;) {
 #ifdef __FreeBSD__
-		IF_LOCK(&ifp->if_snd);
-		_IF_DROP(&ifp->if_snd);
-		_IF_DEQUEUE(&ifp->if_snd, m);
-		IF_UNLOCK(&ifp->if_snd);
+	IF_LOCK(&ifp->if_snd);
+	_IF_DROP(&ifp->if_snd);
+	_IF_DEQUEUE(&ifp->if_snd, m);
+	IF_UNLOCK(&ifp->if_snd);
 #else
-		s = splnet();
-		IF_DROP(&ifp->if_snd);
-		IF_DEQUEUE(&ifp->if_snd, m);
-		splx(s);
+	s = splnet();
+	IF_DEQUEUE(&ifp->if_snd, m);
+	splx(s);
 #endif
 
-		if (m == NULL)
-			return;
-		else
-			m_freem(m);
+	return (m);
+}
+
+/*
+ * Start output on the pfsync interface.
+ */
+void
+pfsyncstart(struct ifnet *ifp)
+{
+	struct mbuf *m;
+
+	while ((m = pfsync_if_dequeue(ifp)) != NULL) {
+#ifndef __FreeBSD__
+		IF_DROP(&ifp->if_snd);
+#endif
+		m_freem(m);
 	}
 }
 
@@ -383,85 +629,196 @@ pfsync_alloc_scrub_memory(struct pfsync_state_peer *s,
     struct pf_state_peer *d)
 {
 	if (s->scrub.scrub_flag && d->scrub == NULL) {
-		d->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+		d->scrub = pool_get(&V_pf_state_scrub_pl, PR_NOWAIT | PR_ZERO);
+#else
+		d->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT | PR_ZERO);
+#endif
 		if (d->scrub == NULL)
 			return (ENOMEM);
-		bzero(d->scrub, sizeof(*d->scrub));
 	}
 
 	return (0);
 }
 
+#ifndef __FreeBSD__
+void
+pfsync_state_export(struct pfsync_state *sp, struct pf_state *st)
+{
+	bzero(sp, sizeof(struct pfsync_state));
+
+	/* copy from state key */
+	sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
+	sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
+	sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
+	sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
+	sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
+	sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
+	sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
+	sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
+	sp->proto = st->key[PF_SK_WIRE]->proto;
+	sp->af = st->key[PF_SK_WIRE]->af;
+
+	/* copy from state */
+	strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
+	bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
+	sp->creation = htonl(time_second - st->creation);
+	sp->expire = pf_state_expires(st);
+	if (sp->expire <= time_second)
+		sp->expire = htonl(0);
+	else
+		sp->expire = htonl(sp->expire - time_second);
+
+	sp->direction = st->direction;
+	sp->log = st->log;
+	sp->timeout = st->timeout;
+	sp->state_flags = st->state_flags;
+	if (st->src_node)
+		sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
+	if (st->nat_src_node)
+		sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
+
+	bcopy(&st->id, &sp->id, sizeof(sp->id));
+	sp->creatorid = st->creatorid;
+	pf_state_peer_hton(&st->src, &sp->src);
+	pf_state_peer_hton(&st->dst, &sp->dst);
+
+	if (st->rule.ptr == NULL)
+		sp->rule = htonl(-1);
+	else
+		sp->rule = htonl(st->rule.ptr->nr);
+	if (st->anchor.ptr == NULL)
+		sp->anchor = htonl(-1);
+	else
+		sp->anchor = htonl(st->anchor.ptr->nr);
+	if (st->nat_rule.ptr == NULL)
+		sp->nat_rule = htonl(-1);
+	else
+		sp->nat_rule = htonl(st->nat_rule.ptr->nr);
+
+	pf_state_counter_hton(st->packets[0], sp->packets[0]);
+	pf_state_counter_hton(st->packets[1], sp->packets[1]);
+	pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
+	pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
+
+}
+#endif
+
 int
-pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
+pfsync_state_import(struct pfsync_state *sp, u_int8_t flags)
 {
 	struct pf_state	*st = NULL;
+	struct pf_state_key *skw = NULL, *sks = NULL;
 	struct pf_rule *r = NULL;
 	struct pfi_kif	*kif;
+	int pool_flags;
+	int error;
 
+#ifdef __FreeBSD__
+	if (sp->creatorid == 0 && V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 	if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
-		printf("pfsync_insert_net_state: invalid creator id:"
+#endif
+		printf("pfsync_state_import: invalid creator id:"
 		    " %08x\n", ntohl(sp->creatorid));
 		return (EINVAL);
 	}
 
-	kif = pfi_kif_get(sp->ifname);
-	if (kif == NULL) {
+	if ((kif = pfi_kif_get(sp->ifname)) == NULL) {
+#ifdef __FreeBSD__
+		if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
 		if (pf_status.debug >= PF_DEBUG_MISC)
-			printf("pfsync_insert_net_state: "
+#endif
+			printf("pfsync_state_import: "
 			    "unknown interface: %s\n", sp->ifname);
-		/* skip this state */
-		return (0);
+		if (flags & PFSYNC_SI_IOCTL)
+			return (EINVAL);
+		return (0);	/* skip this state */
 	}
 
 	/*
-	 * If the ruleset checksums match, it's safe to associate the state
-	 * with the rule of that number.
+	 * If the ruleset checksums match or the state is coming from the ioctl,
+	 * it's safe to associate the state with the rule of that number.
 	 */
-	if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && chksum_flag)
+	if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) &&
+	    (flags & (PFSYNC_SI_IOCTL | PFSYNC_SI_CKSUM)) && ntohl(sp->rule) <
+	    pf_main_ruleset.rules[PF_RULESET_FILTER].active.rcount)
 		r = pf_main_ruleset.rules[
 		    PF_RULESET_FILTER].active.ptr_array[ntohl(sp->rule)];
 	else
+#ifdef __FreeBSD__
+		r = &V_pf_default_rule;
+#else
 		r = &pf_default_rule;
+#endif
 
-	if (!r->max_states || r->states < r->max_states)
-		st = pool_get(&pf_state_pl, PR_NOWAIT);
-	if (st == NULL) {
-		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
-		return (ENOMEM);
-	}
-	bzero(st, sizeof(*st));
+	if ((r->max_states && r->states_cur >= r->max_states))
+		goto cleanup;
 
-	/* allocate memory for scrub info */
-	if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
-	    pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) {
-		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
-		if (st->src.scrub)
-			pool_put(&pf_state_scrub_pl, st->src.scrub);
-		pool_put(&pf_state_pl, st);
-		return (ENOMEM);
-	}
+#ifdef __FreeBSD__
+	if (flags & PFSYNC_SI_IOCTL)
+		pool_flags = PR_WAITOK | PR_ZERO;
+	else
+		pool_flags = PR_ZERO;
 
-	st->rule.ptr = r;
-	/* XXX get pointers to nat_rule and anchor */
+	if ((st = pool_get(&V_pf_state_pl, pool_flags)) == NULL)
+		goto cleanup;
+#else
+	if (flags & PFSYNC_SI_IOCTL)
+		pool_flags = PR_WAITOK | PR_LIMITFAIL | PR_ZERO;
+	else
+		pool_flags = PR_LIMITFAIL | PR_ZERO;
 
-	/* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
-	r->states++;
+	if ((st = pool_get(&pf_state_pl, pool_flags)) == NULL)
+		goto cleanup;
+#endif
 
-	/* fill in the rest of the state entry */
-	pf_state_host_ntoh(&sp->lan, &st->lan);
-	pf_state_host_ntoh(&sp->gwy, &st->gwy);
-	pf_state_host_ntoh(&sp->ext, &st->ext);
+	if ((skw = pf_alloc_state_key(pool_flags)) == NULL)
+		goto cleanup;
 
-	pf_state_peer_ntoh(&sp->src, &st->src);
-	pf_state_peer_ntoh(&sp->dst, &st->dst);
+	if (PF_ANEQ(&sp->key[PF_SK_WIRE].addr[0],
+	    &sp->key[PF_SK_STACK].addr[0], sp->af) ||
+	    PF_ANEQ(&sp->key[PF_SK_WIRE].addr[1],
+	    &sp->key[PF_SK_STACK].addr[1], sp->af) ||
+	    sp->key[PF_SK_WIRE].port[0] != sp->key[PF_SK_STACK].port[0] ||
+	    sp->key[PF_SK_WIRE].port[1] != sp->key[PF_SK_STACK].port[1]) {
+		if ((sks = pf_alloc_state_key(pool_flags)) == NULL)
+			goto cleanup;
+	} else
+		sks = skw;
+
+	/* allocate memory for scrub info */
+	if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
+	    pfsync_alloc_scrub_memory(&sp->dst, &st->dst))
+		goto cleanup;
+
+	/* copy to state key(s) */
+	skw->addr[0] = sp->key[PF_SK_WIRE].addr[0];
+	skw->addr[1] = sp->key[PF_SK_WIRE].addr[1];
+	skw->port[0] = sp->key[PF_SK_WIRE].port[0];
+	skw->port[1] = sp->key[PF_SK_WIRE].port[1];
+	skw->proto = sp->proto;
+	skw->af = sp->af;
+	if (sks != skw) {
+		sks->addr[0] = sp->key[PF_SK_STACK].addr[0];
+		sks->addr[1] = sp->key[PF_SK_STACK].addr[1];
+		sks->port[0] = sp->key[PF_SK_STACK].port[0];
+		sks->port[1] = sp->key[PF_SK_STACK].port[1];
+		sks->proto = sp->proto;
+		sks->af = sp->af;
+	}
 
+	/* copy to state */
 	bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
 	st->creation = time_second - ntohl(sp->creation);
-	st->expire = ntohl(sp->expire) + time_second;
+	st->expire = time_second;
+	if (sp->expire) {
+		/* XXX No adaptive scaling. */
+		st->expire -= r->timeout[sp->timeout] - ntohl(sp->expire);
+	}
 
-	st->af = sp->af;
-	st->proto = sp->proto;
+	st->expire = ntohl(sp->expire) + time_second;
 	st->direction = sp->direction;
 	st->log = sp->log;
 	st->timeout = sp->timeout;
@@ -469,621 +826,942 @@ pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
 
 	bcopy(sp->id, &st->id, sizeof(st->id));
 	st->creatorid = sp->creatorid;
-	st->sync_flags = PFSTATE_FROMSYNC;
+	pf_state_peer_ntoh(&sp->src, &st->src);
+	pf_state_peer_ntoh(&sp->dst, &st->dst);
 
-	if (pf_insert_state(kif, st)) {
-		pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+	st->rule.ptr = r;
+	st->nat_rule.ptr = NULL;
+	st->anchor.ptr = NULL;
+	st->rt_kif = NULL;
+
+	st->pfsync_time = time_second;
+	st->sync_state = PFSYNC_S_NONE;
+
+	/* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
+	r->states_cur++;
+	r->states_tot++;
+
+	if (!ISSET(flags, PFSYNC_SI_IOCTL))
+		SET(st->state_flags, PFSTATE_NOSYNC);
+
+	if ((error = pf_state_insert(kif, skw, sks, st)) != 0) {
 		/* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
-		r->states--;
-		if (st->dst.scrub)
-			pool_put(&pf_state_scrub_pl, st->dst.scrub);
-		if (st->src.scrub)
-			pool_put(&pf_state_scrub_pl, st->src.scrub);
-		pool_put(&pf_state_pl, st);
-		return (EINVAL);
+		r->states_cur--;
+		goto cleanup_state;
 	}
 
+	if (!ISSET(flags, PFSYNC_SI_IOCTL)) {
+		CLR(st->state_flags, PFSTATE_NOSYNC);
+		if (ISSET(st->state_flags, PFSTATE_ACK)) {
+			pfsync_q_ins(st, PFSYNC_S_IACK);
+			schednetisr(NETISR_PFSYNC);
+		}
+	}
+	CLR(st->state_flags, PFSTATE_ACK);
+
 	return (0);
-}
 
-void
+cleanup:
+	error = ENOMEM;
+	if (skw == sks)
+		sks = NULL;
 #ifdef __FreeBSD__
-pfsync_input(struct mbuf *m, __unused int off)
+	if (skw != NULL)
+		pool_put(&V_pf_state_key_pl, skw);
+	if (sks != NULL)
+		pool_put(&V_pf_state_key_pl, sks);
 #else
-pfsync_input(struct mbuf *m, ...)
+	if (skw != NULL)
+		pool_put(&pf_state_key_pl, skw);
+	if (sks != NULL)
+		pool_put(&pf_state_key_pl, sks);
 #endif
-{
-	struct ip *ip = mtod(m, struct ip *);
-	struct pfsync_header *ph;
-	struct pfsync_softc *sc = pfsyncif;
-	struct pf_state *st;
-	struct pf_state_cmp key;
-	struct pfsync_state *sp;
-	struct pfsync_state_upd *up;
-	struct pfsync_state_del *dp;
-	struct pfsync_state_clr *cp;
-	struct pfsync_state_upd_req *rup;
-	struct pfsync_state_bus *bus;
-#ifdef PFSYNC_TDB
-	struct pfsync_tdb *pt;
+
+cleanup_state:	/* pf_state_insert frees the state keys */
+	if (st) {
+#ifdef __FreeBSD__
+		if (st->dst.scrub)
+			pool_put(&V_pf_state_scrub_pl, st->dst.scrub);
+		if (st->src.scrub)
+			pool_put(&V_pf_state_scrub_pl, st->src.scrub);
+		pool_put(&V_pf_state_pl, st);
+#else
+		if (st->dst.scrub)
+			pool_put(&pf_state_scrub_pl, st->dst.scrub);
+		if (st->src.scrub)
+			pool_put(&pf_state_scrub_pl, st->src.scrub);
+		pool_put(&pf_state_pl, st);
 #endif
-	struct in_addr src;
-	struct mbuf *mp;
-	int iplen, action, error, i, s, count, offp, sfail, stale = 0;
-	u_int8_t chksum_flag = 0;
+	}
+	return (error);
+}
+
+void
+#ifdef __FreeBSD__
+pfsync_input(struct mbuf *m, __unused int off)
+#else
+pfsync_input(struct mbuf *m, ...)
+#endif
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+	struct pfsync_pkt pkt;
+	struct ip *ip = mtod(m, struct ip *);
+	struct pfsync_header *ph;
+	struct pfsync_subheader subh;
 
-	pfsyncstats.pfsyncs_ipackets++;
+	int offset;
+	int rv;
+
+	V_pfsyncstats.pfsyncs_ipackets++;
 
 	/* verify that we have a sync interface configured */
-	if (!sc || !sc->sc_sync_ifp || !pf_status.running)
+#ifdef __FreeBSD__
+	if (!sc || !sc->sc_sync_if || !V_pf_status.running)
+#else
+	if (!sc || !sc->sc_sync_if || !pf_status.running)
+#endif
 		goto done;
 
 	/* verify that the packet came in on the right interface */
-	if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
-		pfsyncstats.pfsyncs_badif++;
+	if (sc->sc_sync_if != m->m_pkthdr.rcvif) {
+		V_pfsyncstats.pfsyncs_badif++;
 		goto done;
 	}
 
-	/* verify that the IP TTL is 255.  */
+#ifdef __FreeBSD__
+	sc->sc_ifp->if_ipackets++;
+	sc->sc_ifp->if_ibytes += m->m_pkthdr.len;
+#else
+	sc->sc_if.if_ipackets++;
+	sc->sc_if.if_ibytes += m->m_pkthdr.len;
+#endif
+	/* verify that the IP TTL is 255. */
 	if (ip->ip_ttl != PFSYNC_DFLTTL) {
-		pfsyncstats.pfsyncs_badttl++;
+		V_pfsyncstats.pfsyncs_badttl++;
 		goto done;
 	}
 
-	iplen = ip->ip_hl << 2;
-
-	if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
-		pfsyncstats.pfsyncs_hdrops++;
+	offset = ip->ip_hl << 2;
+	if (m->m_pkthdr.len < offset + sizeof(*ph)) {
+		V_pfsyncstats.pfsyncs_hdrops++;
 		goto done;
 	}
 
-	if (iplen + sizeof(*ph) > m->m_len) {
-		if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
-			pfsyncstats.pfsyncs_hdrops++;
-			goto done;
+	if (offset + sizeof(*ph) > m->m_len) {
+		if (m_pullup(m, offset + sizeof(*ph)) == NULL) {
+			V_pfsyncstats.pfsyncs_hdrops++;
+			return;
 		}
 		ip = mtod(m, struct ip *);
 	}
-	ph = (struct pfsync_header *)((char *)ip + iplen);
+	ph = (struct pfsync_header *)((char *)ip + offset);
 
 	/* verify the version */
 	if (ph->version != PFSYNC_VERSION) {
-		pfsyncstats.pfsyncs_badver++;
+		V_pfsyncstats.pfsyncs_badver++;
 		goto done;
 	}
 
-	action = ph->action;
-	count = ph->count;
-
-	/* make sure it's a valid action code */
-	if (action >= PFSYNC_ACT_MAX) {
-		pfsyncstats.pfsyncs_badact++;
+#if 0
+	if (pfsync_input_hmac(m, offset) != 0) {
+		/* XXX stats */
 		goto done;
 	}
+#endif
 
 	/* Cheaper to grab this now than having to mess with mbufs later */
-	src = ip->ip_src;
-
-	if (!bcmp(&ph->pf_chksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
-		chksum_flag++;
-
-	switch (action) {
-	case PFSYNC_ACT_CLR: {
-		struct pf_state *nexts;
-		struct pfi_kif	*kif;
-		u_int32_t creatorid;
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    sizeof(*cp), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
+	pkt.ip = ip;
+	pkt.src = ip->ip_src;
+	pkt.flags = 0;
+
+#ifdef __FreeBSD__
+	if (!bcmp(&ph->pfcksum, &V_pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
+#else
+	if (!bcmp(&ph->pfcksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
+#endif
+		pkt.flags |= PFSYNC_SI_CKSUM;
+
+	offset += sizeof(*ph);
+	for (;;) {
+		m_copydata(m, offset, sizeof(subh), (caddr_t)&subh);
+		offset += sizeof(subh);
+
+		if (subh.action >= PFSYNC_ACT_MAX) {
+			V_pfsyncstats.pfsyncs_badact++;
+			goto done;
 		}
-		cp = (struct pfsync_state_clr *)(mp->m_data + offp);
-		creatorid = cp->creatorid;
 
-		s = splsoftnet();
+		rv = (*pfsync_acts[subh.action])(&pkt, m, offset,
+		    ntohs(subh.count));
+		if (rv == -1)
+			return;
+
+		offset += rv;
+	}
+
+done:
+	m_freem(m);
+}
+
+int
+pfsync_in_clr(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct pfsync_clr *clr;
+	struct mbuf *mp;
+	int len = sizeof(*clr) * count;
+	int i, offp;
+
+	struct pf_state *st, *nexts;
+	struct pf_state_key *sk, *nextsk;
+	struct pf_state_item *si;
+	u_int32_t creatorid;
+	int s;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	clr = (struct pfsync_clr *)(mp->m_data + offp);
+
+	s = splsoftnet();
 #ifdef __FreeBSD__
-		PF_LOCK();
+	PF_LOCK();
 #endif
-		if (cp->ifname[0] == '\0') {
+	for (i = 0; i < count; i++) {
+		creatorid = clr[i].creatorid;
+
+		if (clr[i].ifname[0] == '\0') {
+#ifdef __FreeBSD__
+			for (st = RB_MIN(pf_state_tree_id, &V_tree_id);
+			    st; st = nexts) {
+				nexts = RB_NEXT(pf_state_tree_id, &V_tree_id, st);
+#else
 			for (st = RB_MIN(pf_state_tree_id, &tree_id);
 			    st; st = nexts) {
 				nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
+#endif
 				if (st->creatorid == creatorid) {
-					st->sync_flags |= PFSTATE_FROMSYNC;
+					SET(st->state_flags, PFSTATE_NOSYNC);
 					pf_unlink_state(st);
 				}
 			}
 		} else {
-			if ((kif = pfi_kif_get(cp->ifname)) == NULL) {
+			if (pfi_kif_get(clr[i].ifname) == NULL)
+				continue;
+
+			/* XXX correct? */
 #ifdef __FreeBSD__
-				PF_UNLOCK();
+			for (sk = RB_MIN(pf_state_tree, &V_pf_statetbl);
+#else
+			for (sk = RB_MIN(pf_state_tree, &pf_statetbl);
 #endif
-				splx(s);
-				return;
-			}
-			for (st = RB_MIN(pf_state_tree_lan_ext,
-			    &kif->pfik_lan_ext); st; st = nexts) {
-				nexts = RB_NEXT(pf_state_tree_lan_ext,
-				    &kif->pfik_lan_ext, st);
-				if (st->creatorid == creatorid) {
-					st->sync_flags |= PFSTATE_FROMSYNC;
-					pf_unlink_state(st);
+			    sk; sk = nextsk) {
+				nextsk = RB_NEXT(pf_state_tree,
+#ifdef __FreeBSD__
+				    &V_pf_statetbl, sk);
+#else
+				    &pf_statetbl, sk);
+#endif
+				TAILQ_FOREACH(si, &sk->states, entry) {
+					if (si->s->creatorid == creatorid) {
+						SET(si->s->state_flags,
+						    PFSTATE_NOSYNC);
+						pf_unlink_state(si->s);
+					}
 				}
 			}
 		}
+	}
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+	PF_UNLOCK();
 #endif
-		splx(s);
+	splx(s);
 
-		break;
+	return (len);
+}
+
+int
+pfsync_in_ins(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct mbuf *mp;
+	struct pfsync_state *sa, *sp;
+	int len = sizeof(*sp) * count;
+	int i, offp;
+
+	int s;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
 	}
-	case PFSYNC_ACT_INS:
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    count * sizeof(*sp), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
-		}
+	sa = (struct pfsync_state *)(mp->m_data + offp);
 
-		s = splsoftnet();
+	s = splsoftnet();
 #ifdef __FreeBSD__
-		PF_LOCK();
+	PF_LOCK();
 #endif
-		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
-		    i < count; i++, sp++) {
-			/* check for invalid values */
-			if (sp->timeout >= PFTM_MAX ||
-			    sp->src.state > PF_TCPS_PROXY_DST ||
-			    sp->dst.state > PF_TCPS_PROXY_DST ||
-			    sp->direction > PF_OUT ||
-			    (sp->af != AF_INET && sp->af != AF_INET6)) {
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync_insert: PFSYNC_ACT_INS: "
-					    "invalid value\n");
-				pfsyncstats.pfsyncs_badstate++;
-				continue;
-			}
+	for (i = 0; i < count; i++) {
+		sp = &sa[i];
 
-			if ((error = pfsync_insert_net_state(sp,
-			    chksum_flag))) {
-				if (error == ENOMEM) {
+		/* check for invalid values */
+		if (sp->timeout >= PFTM_MAX ||
+		    sp->src.state > PF_TCPS_PROXY_DST ||
+		    sp->dst.state > PF_TCPS_PROXY_DST ||
+		    sp->direction > PF_OUT ||
+		    (sp->af != AF_INET && sp->af != AF_INET6)) {
 #ifdef __FreeBSD__
-					PF_UNLOCK();
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC) {
 #endif
-					splx(s);
-					goto done;
-				}
-				continue;
+				printf("pfsync_input: PFSYNC5_ACT_INS: "
+				    "invalid value\n");
 			}
+			V_pfsyncstats.pfsyncs_badval++;
+			continue;
 		}
+
+		if (pfsync_state_import(sp, pkt->flags) == ENOMEM) {
+			/* drop out, but process the rest of the actions */
+			break;
+		}
+	}
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+	PF_UNLOCK();
 #endif
-		splx(s);
-		break;
-	case PFSYNC_ACT_UPD:
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    count * sizeof(*sp), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
-		}
+	splx(s);
+
+	return (len);
+}
+
+int
+pfsync_in_iack(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct pfsync_ins_ack *ia, *iaa;
+	struct pf_state_cmp id_key;
+	struct pf_state *st;
+
+	struct mbuf *mp;
+	int len = count * sizeof(*ia);
+	int offp, i;
+	int s;
 
-		s = splsoftnet();
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	iaa = (struct pfsync_ins_ack *)(mp->m_data + offp);
+
+	s = splsoftnet();
 #ifdef __FreeBSD__
-		PF_LOCK();
+	PF_LOCK();
 #endif
-		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
-		    i < count; i++, sp++) {
-			int flags = PFSYNC_FLAG_STALE;
-
-			/* check for invalid values */
-			if (sp->timeout >= PFTM_MAX ||
-			    sp->src.state > PF_TCPS_PROXY_DST ||
-			    sp->dst.state > PF_TCPS_PROXY_DST) {
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync_insert: PFSYNC_ACT_UPD: "
-					    "invalid value\n");
-				pfsyncstats.pfsyncs_badstate++;
-				continue;
-			}
+	for (i = 0; i < count; i++) {
+		ia = &iaa[i];
 
-			bcopy(sp->id, &key.id, sizeof(key.id));
-			key.creatorid = sp->creatorid;
+		bcopy(&ia->id, &id_key.id, sizeof(id_key.id));
+		id_key.creatorid = ia->creatorid;
 
-			st = pf_find_state_byid(&key);
-			if (st == NULL) {
-				/* insert the update */
-				if (pfsync_insert_net_state(sp, chksum_flag))
-					pfsyncstats.pfsyncs_badstate++;
-				continue;
-			}
-			sfail = 0;
-			if (st->proto == IPPROTO_TCP) {
-				/*
-				 * The state should never go backwards except
-				 * for syn-proxy states.  Neither should the
-				 * sequence window slide backwards.
-				 */
-				if (st->src.state > sp->src.state &&
-				    (st->src.state < PF_TCPS_PROXY_SRC ||
-				    sp->src.state >= PF_TCPS_PROXY_SRC))
-					sfail = 1;
-				else if (SEQ_GT(st->src.seqlo,
-				    ntohl(sp->src.seqlo)))
-					sfail = 3;
-				else if (st->dst.state > sp->dst.state) {
-					/* There might still be useful
-					 * information about the src state here,
-					 * so import that part of the update,
-					 * then "fail" so we send the updated
-					 * state back to the peer who is missing
-					 * our what we know. */
-					pf_state_peer_ntoh(&sp->src, &st->src);
-					/* XXX do anything with timeouts? */
-					sfail = 7;
-					flags = 0;
-				} else if (st->dst.state >= TCPS_SYN_SENT &&
-				    SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
-					sfail = 4;
-			} else {
-				/*
-				 * Non-TCP protocol state machine always go
-				 * forwards
-				 */
-				if (st->src.state > sp->src.state)
-					sfail = 5;
-				else if (st->dst.state > sp->dst.state)
-					sfail = 6;
-			}
-			if (sfail) {
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync: %s stale update "
-					    "(%d) id: %016llx "
-					    "creatorid: %08x\n",
-					    (sfail < 7 ?  "ignoring"
-					     : "partial"), sfail,
-					    betoh64(st->id),
-					    ntohl(st->creatorid));
-				pfsyncstats.pfsyncs_badstate++;
-
-				if (!(sp->sync_flags & PFSTATE_STALE)) {
-					/* we have a better state, send it */
-					if (sc->sc_mbuf != NULL && !stale)
-						pfsync_sendout(sc);
-					stale++;
-					if (!st->sync_flags)
-						pfsync_pack_state(
-						    PFSYNC_ACT_UPD, st, flags);
-				}
-				continue;
-			}
-	    		pfsync_alloc_scrub_memory(&sp->dst, &st->dst);
-			pf_state_peer_ntoh(&sp->src, &st->src);
-			pf_state_peer_ntoh(&sp->dst, &st->dst);
-			st->expire = ntohl(sp->expire) + time_second;
-			st->timeout = sp->timeout;
-		}
-		if (stale && sc->sc_mbuf != NULL)
-			pfsync_sendout(sc);
+		st = pf_find_state_byid(&id_key);
+		if (st == NULL)
+			continue;
+
+		if (ISSET(st->state_flags, PFSTATE_ACK))
+			pfsync_deferred(st, 0);
+	}
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+	PF_UNLOCK();
 #endif
-		splx(s);
-		break;
+	splx(s);
 	/*
-	 * It's not strictly necessary for us to support the "uncompressed"
-	 * delete action, but it's relatively simple and maintains consistency.
+	 * XXX this is not yet implemented, but we know the size of the
+	 * message so we can skip it.
 	 */
-	case PFSYNC_ACT_DEL:
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    count * sizeof(*sp), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
-		}
 
-		s = splsoftnet();
+	return (count * sizeof(struct pfsync_ins_ack));
+}
+
+int
+pfsync_upd_tcp(struct pf_state *st, struct pfsync_state_peer *src,
+    struct pfsync_state_peer *dst)
+{
+	int sfail = 0;
+
+	/*
+	 * The state should never go backwards except
+	 * for syn-proxy states.  Neither should the
+	 * sequence window slide backwards.
+	 */
+	if (st->src.state > src->state &&
+	    (st->src.state < PF_TCPS_PROXY_SRC ||
+	    src->state >= PF_TCPS_PROXY_SRC))
+		sfail = 1;
+	else if (SEQ_GT(st->src.seqlo, ntohl(src->seqlo)))
+		sfail = 3;
+	else if (st->dst.state > dst->state) {
+		/* There might still be useful
+		 * information about the src state here,
+		 * so import that part of the update,
+		 * then "fail" so we send the updated
+		 * state back to the peer who is missing
+		 * our what we know. */
+		pf_state_peer_ntoh(src, &st->src);
+		/* XXX do anything with timeouts? */
+		sfail = 7;
+	} else if (st->dst.state >= TCPS_SYN_SENT &&
+	    SEQ_GT(st->dst.seqlo, ntohl(dst->seqlo)))
+		sfail = 4;
+
+	return (sfail);
+}
+
+int
+pfsync_in_upd(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct pfsync_state *sa, *sp;
+	struct pf_state_cmp id_key;
+	struct pf_state_key *sk;
+	struct pf_state *st;
+	int sfail;
+
+	struct mbuf *mp;
+	int len = count * sizeof(*sp);
+	int offp, i;
+	int s;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	sa = (struct pfsync_state *)(mp->m_data + offp);
+
+	s = splsoftnet();
 #ifdef __FreeBSD__
-		PF_LOCK();
+	PF_LOCK();
 #endif
-		for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
-		    i < count; i++, sp++) {
-			bcopy(sp->id, &key.id, sizeof(key.id));
-			key.creatorid = sp->creatorid;
+	for (i = 0; i < count; i++) {
+		sp = &sa[i];
 
-			st = pf_find_state_byid(&key);
-			if (st == NULL) {
-				pfsyncstats.pfsyncs_badstate++;
-				continue;
-			}
-			st->sync_flags |= PFSTATE_FROMSYNC;
-			pf_unlink_state(st);
-		}
+		/* check for invalid values */
+		if (sp->timeout >= PFTM_MAX ||
+		    sp->src.state > PF_TCPS_PROXY_DST ||
+		    sp->dst.state > PF_TCPS_PROXY_DST) {
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC) {
 #endif
-		splx(s);
-		break;
-	case PFSYNC_ACT_UPD_C: {
-		int update_requested = 0;
+				printf("pfsync_input: PFSYNC_ACT_UPD: "
+				    "invalid value\n");
+			}
+			V_pfsyncstats.pfsyncs_badval++;
+			continue;
+		}
 
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    count * sizeof(*up), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
+		bcopy(sp->id, &id_key.id, sizeof(id_key.id));
+		id_key.creatorid = sp->creatorid;
+
+		st = pf_find_state_byid(&id_key);
+		if (st == NULL) {
+			/* insert the update */
+			if (pfsync_state_import(sp, 0))
+				V_pfsyncstats.pfsyncs_badstate++;
+			continue;
 		}
 
-		s = splsoftnet();
-#ifdef __FreeBSD__
-		PF_LOCK();
-#endif
-		for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
-		    i < count; i++, up++) {
-			/* check for invalid values */
-			if (up->timeout >= PFTM_MAX ||
-			    up->src.state > PF_TCPS_PROXY_DST ||
-			    up->dst.state > PF_TCPS_PROXY_DST) {
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync_insert: "
-					    "PFSYNC_ACT_UPD_C: "
-					    "invalid value\n");
-				pfsyncstats.pfsyncs_badstate++;
-				continue;
-			}
+		if (ISSET(st->state_flags, PFSTATE_ACK))
+			pfsync_deferred(st, 1);
 
-			bcopy(up->id, &key.id, sizeof(key.id));
-			key.creatorid = up->creatorid;
+		sk = st->key[PF_SK_WIRE];	/* XXX right one? */
+		sfail = 0;
+		if (sk->proto == IPPROTO_TCP)
+			sfail = pfsync_upd_tcp(st, &sp->src, &sp->dst);
+		else {
+			/*
+			 * Non-TCP protocol state machine always go
+			 * forwards
+			 */
+			if (st->src.state > sp->src.state)
+				sfail = 5;
+			else if (st->dst.state > sp->dst.state)
+				sfail = 6;
+		}
 
-			st = pf_find_state_byid(&key);
-			if (st == NULL) {
-				/* We don't have this state. Ask for it. */
-				error = pfsync_request_update(up, &src);
-				if (error == ENOMEM) {
+		if (sfail) {
 #ifdef __FreeBSD__
-					PF_UNLOCK();
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC) {
 #endif
-					splx(s);
-					goto done;
-				}
-				update_requested = 1;
-				pfsyncstats.pfsyncs_badstate++;
-				continue;
-			}
-			sfail = 0;
-			if (st->proto == IPPROTO_TCP) {
-				/*
-				 * The state should never go backwards except
-				 * for syn-proxy states.  Neither should the
-				 * sequence window slide backwards.
-				 */
-				if (st->src.state > up->src.state &&
-				    (st->src.state < PF_TCPS_PROXY_SRC ||
-				    up->src.state >= PF_TCPS_PROXY_SRC))
-					sfail = 1;
-				else if (st->dst.state > up->dst.state)
-					sfail = 2;
-				else if (SEQ_GT(st->src.seqlo,
-				    ntohl(up->src.seqlo)))
-					sfail = 3;
-				else if (st->dst.state >= TCPS_SYN_SENT &&
-				    SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
-					sfail = 4;
-			} else {
-				/*
-				 * Non-TCP protocol state machine always go
-				 * forwards
-				 */
-				if (st->src.state > up->src.state)
-					sfail = 5;
-				else if (st->dst.state > up->dst.state)
-					sfail = 6;
-			}
-			if (sfail) {
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync: ignoring stale update "
-					    "(%d) id: %016llx "
-					    "creatorid: %08x\n", sfail,
-					    betoh64(st->id),
-					    ntohl(st->creatorid));
-				pfsyncstats.pfsyncs_badstate++;
-
-				/* we have a better state, send it out */
-				if ((!stale || update_requested) &&
-				    sc->sc_mbuf != NULL) {
-					pfsync_sendout(sc);
-					update_requested = 0;
-				}
-				stale++;
-				if (!st->sync_flags)
-					pfsync_pack_state(PFSYNC_ACT_UPD, st,
-					    PFSYNC_FLAG_STALE);
-				continue;
+				printf("pfsync: %s stale update (%d)"
+				    " id: %016llx creatorid: %08x\n",
+				    (sfail < 7 ?  "ignoring" : "partial"),
+				    sfail, betoh64(st->id),
+				    ntohl(st->creatorid));
 			}
-	    		pfsync_alloc_scrub_memory(&up->dst, &st->dst);
-			pf_state_peer_ntoh(&up->src, &st->src);
-			pf_state_peer_ntoh(&up->dst, &st->dst);
-			st->expire = ntohl(up->expire) + time_second;
-			st->timeout = up->timeout;
+			V_pfsyncstats.pfsyncs_stale++;
+
+			pfsync_update_state(st);
+			schednetisr(NETISR_PFSYNC);
+			continue;
 		}
-		if ((update_requested || stale) && sc->sc_mbuf)
-			pfsync_sendout(sc);
+		pfsync_alloc_scrub_memory(&sp->dst, &st->dst);
+		pf_state_peer_ntoh(&sp->src, &st->src);
+		pf_state_peer_ntoh(&sp->dst, &st->dst);
+		st->expire = ntohl(sp->expire) + time_second;
+		st->timeout = sp->timeout;
+		st->pfsync_time = time_second;
+	}
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+	PF_UNLOCK();
 #endif
-		splx(s);
-		break;
+	splx(s);
+
+	return (len);
+}
+
+int
+pfsync_in_upd_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct pfsync_upd_c *ua, *up;
+	struct pf_state_key *sk;
+	struct pf_state_cmp id_key;
+	struct pf_state *st;
+
+	int len = count * sizeof(*up);
+	int sfail;
+
+	struct mbuf *mp;
+	int offp, i;
+	int s;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
 	}
-	case PFSYNC_ACT_DEL_C:
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    count * sizeof(*dp), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
-		}
+	ua = (struct pfsync_upd_c *)(mp->m_data + offp);
 
-		s = splsoftnet();
+	s = splsoftnet();
 #ifdef __FreeBSD__
-		PF_LOCK();
+	PF_LOCK();
 #endif
-		for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
-		    i < count; i++, dp++) {
-			bcopy(dp->id, &key.id, sizeof(key.id));
-			key.creatorid = dp->creatorid;
+	for (i = 0; i < count; i++) {
+		up = &ua[i];
 
-			st = pf_find_state_byid(&key);
-			if (st == NULL) {
-				pfsyncstats.pfsyncs_badstate++;
-				continue;
-			}
-			st->sync_flags |= PFSTATE_FROMSYNC;
-			pf_unlink_state(st);
-		}
+		/* check for invalid values */
+		if (up->timeout >= PFTM_MAX ||
+		    up->src.state > PF_TCPS_PROXY_DST ||
+		    up->dst.state > PF_TCPS_PROXY_DST) {
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC) {
 #endif
-		splx(s);
-		break;
-	case PFSYNC_ACT_INS_F:
-	case PFSYNC_ACT_DEL_F:
-		/* not implemented */
-		break;
-	case PFSYNC_ACT_UREQ:
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    count * sizeof(*rup), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
+				printf("pfsync_input: "
+				    "PFSYNC_ACT_UPD_C: "
+				    "invalid value\n");
+			}
+			V_pfsyncstats.pfsyncs_badval++;
+			continue;
 		}
 
-		s = splsoftnet();
-#ifdef __FreeBSD__
-		PF_LOCK();
-#endif
-		if (sc->sc_mbuf != NULL)
-			pfsync_sendout(sc);
-		for (i = 0,
-		    rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
-		    i < count; i++, rup++) {
-			bcopy(rup->id, &key.id, sizeof(key.id));
-			key.creatorid = rup->creatorid;
-
-			if (key.id == 0 && key.creatorid == 0) {
-				sc->sc_ureq_received = time_uptime;
-				if (sc->sc_bulk_send_next == NULL)
-					sc->sc_bulk_send_next =
-					    TAILQ_FIRST(&state_list);
-				sc->sc_bulk_terminator = sc->sc_bulk_send_next;
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync: received "
-					    "bulk update request\n");
-				pfsync_send_bus(sc, PFSYNC_BUS_START);
-#ifdef __FreeBSD__
-				callout_reset(&sc->sc_bulk_tmo, 1 * hz,
-				    pfsync_bulk_update, pfsyncif);
-#else
-				timeout_add(&sc->sc_bulk_tmo, 1 * hz);
-#endif
-			} else {
-				st = pf_find_state_byid(&key);
-				if (st == NULL) {
-					pfsyncstats.pfsyncs_badstate++;
-					continue;
-				}
-				if (!st->sync_flags)
-					pfsync_pack_state(PFSYNC_ACT_UPD,
-					    st, 0);
-			}
+		bcopy(&up->id, &id_key.id, sizeof(id_key.id));
+		id_key.creatorid = up->creatorid;
+
+		st = pf_find_state_byid(&id_key);
+		if (st == NULL) {
+			/* We don't have this state. Ask for it. */
+			pfsync_request_update(id_key.creatorid, id_key.id);
+			continue;
 		}
-		if (sc->sc_mbuf != NULL)
-			pfsync_sendout(sc);
-#ifdef __FreeBSD__
-		PF_UNLOCK();
-#endif
-		splx(s);
-		break;
-	case PFSYNC_ACT_BUS:
-		/* If we're not waiting for a bulk update, who cares. */
-		if (sc->sc_ureq_sent == 0)
-			break;
 
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    sizeof(*bus), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
+		if (ISSET(st->state_flags, PFSTATE_ACK))
+			pfsync_deferred(st, 1);
+
+		sk = st->key[PF_SK_WIRE]; /* XXX right one? */
+		sfail = 0;
+		if (sk->proto == IPPROTO_TCP)
+			sfail = pfsync_upd_tcp(st, &up->src, &up->dst);
+		else {
+			/*
+			 * Non-TCP protocol state machine always go forwards
+			 */
+			if (st->src.state > up->src.state)
+				sfail = 5;
+			else if (st->dst.state > up->dst.state)
+				sfail = 6;
 		}
-		bus = (struct pfsync_state_bus *)(mp->m_data + offp);
-		switch (bus->status) {
-		case PFSYNC_BUS_START:
+
+		if (sfail) {
 #ifdef __FreeBSD__
-			callout_reset(&sc->sc_bulkfail_tmo,
-			    pf_pool_limits[PF_LIMIT_STATES].limit /
-			    (PFSYNC_BULKPACKETS * sc->sc_maxcount),
-			    pfsync_bulkfail, pfsyncif);
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
 #else
-			timeout_add(&sc->sc_bulkfail_tmo,
-			    pf_pool_limits[PF_LIMIT_STATES].limit /
-			    (PFSYNC_BULKPACKETS * sc->sc_maxcount));
+			if (pf_status.debug >= PF_DEBUG_MISC) {
 #endif
-			if (pf_status.debug >= PF_DEBUG_MISC)
-				printf("pfsync: received bulk "
-				    "update start\n");
-			break;
-		case PFSYNC_BUS_END:
-			if (time_uptime - ntohl(bus->endtime) >=
-			    sc->sc_ureq_sent) {
-				/* that's it, we're happy */
-				sc->sc_ureq_sent = 0;
-				sc->sc_bulk_tries = 0;
-				timeout_del(&sc->sc_bulkfail_tmo);
+				printf("pfsync: ignoring stale update "
+				    "(%d) id: %016llx "
+				    "creatorid: %08x\n", sfail,
+				    betoh64(st->id),
+				    ntohl(st->creatorid));
+			}
+			V_pfsyncstats.pfsyncs_stale++;
+
+			pfsync_update_state(st);
+			schednetisr(NETISR_PFSYNC);
+			continue;
+		}
+		pfsync_alloc_scrub_memory(&up->dst, &st->dst);
+		pf_state_peer_ntoh(&up->src, &st->src);
+		pf_state_peer_ntoh(&up->dst, &st->dst);
+		st->expire = ntohl(up->expire) + time_second;
+		st->timeout = up->timeout;
+		st->pfsync_time = time_second;
+	}
+#ifdef __FreeBSD__
+	PF_UNLOCK();
+#endif
+	splx(s);
+
+	return (len);
+}
+
+int
+pfsync_in_ureq(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct pfsync_upd_req *ur, *ura;
+	struct mbuf *mp;
+	int len = count * sizeof(*ur);
+	int i, offp;
+
+	struct pf_state_cmp id_key;
+	struct pf_state *st;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	ura = (struct pfsync_upd_req *)(mp->m_data + offp);
+
+	for (i = 0; i < count; i++) {
+		ur = &ura[i];
+
+		bcopy(&ur->id, &id_key.id, sizeof(id_key.id));
+		id_key.creatorid = ur->creatorid;
+
+		if (id_key.id == 0 && id_key.creatorid == 0)
+			pfsync_bulk_start();
+		else {
+			st = pf_find_state_byid(&id_key);
+			if (st == NULL) {
+				V_pfsyncstats.pfsyncs_badstate++;
+				continue;
+			}
+			if (ISSET(st->state_flags, PFSTATE_NOSYNC))
+				continue;
+
+			pfsync_update_state_req(st);
+		}
+	}
+
+	return (len);
+}
+
+int
+pfsync_in_del(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct mbuf *mp;
+	struct pfsync_state *sa, *sp;
+	struct pf_state_cmp id_key;
+	struct pf_state *st;
+	int len = count * sizeof(*sp);
+	int offp, i;
+	int s;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	sa = (struct pfsync_state *)(mp->m_data + offp);
+
+	s = splsoftnet();
+#ifdef __FreeBSD__
+	PF_LOCK();
+#endif
+	for (i = 0; i < count; i++) {
+		sp = &sa[i];
+
+		bcopy(sp->id, &id_key.id, sizeof(id_key.id));
+		id_key.creatorid = sp->creatorid;
+
+		st = pf_find_state_byid(&id_key);
+		if (st == NULL) {
+			V_pfsyncstats.pfsyncs_badstate++;
+			continue;
+		}
+		SET(st->state_flags, PFSTATE_NOSYNC);
+		pf_unlink_state(st);
+	}
+#ifdef __FreeBSD__
+	PF_UNLOCK();
+#endif
+	splx(s);
+
+	return (len);
+}
+
+int
+pfsync_in_del_c(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	struct mbuf *mp;
+	struct pfsync_del_c *sa, *sp;
+	struct pf_state_cmp id_key;
+	struct pf_state *st;
+	int len = count * sizeof(*sp);
+	int offp, i;
+	int s;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	sa = (struct pfsync_del_c *)(mp->m_data + offp);
+
+	s = splsoftnet();
+#ifdef __FreeBSD__
+	PF_LOCK();
+#endif
+	for (i = 0; i < count; i++) {
+		sp = &sa[i];
+
+		bcopy(&sp->id, &id_key.id, sizeof(id_key.id));
+		id_key.creatorid = sp->creatorid;
+
+		st = pf_find_state_byid(&id_key);
+		if (st == NULL) {
+			V_pfsyncstats.pfsyncs_badstate++;
+			continue;
+		}
+
+		SET(st->state_flags, PFSTATE_NOSYNC);
+		pf_unlink_state(st);
+	}
+#ifdef __FreeBSD__
+	PF_LOCK();
+#endif
+	splx(s);
+
+	return (len);
+}
+
+int
+pfsync_in_bus(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+	struct pfsync_bus *bus;
+	struct mbuf *mp;
+	int len = count * sizeof(*bus);
+	int offp;
+
+	/* If we're not waiting for a bulk update, who cares. */
+	if (sc->sc_ureq_sent == 0)
+		return (len);
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	bus = (struct pfsync_bus *)(mp->m_data + offp);
+
+	switch (bus->status) {
+	case PFSYNC_BUS_START:
+#ifdef __FreeBSD__
+		callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulk_fail,
+		    V_pfsyncif);
+#else
+		timeout_add_sec(&sc->sc_bulkfail_tmo, 5); /* XXX magic */
+#endif
+#ifdef XXX
+		    pf_pool_limits[PF_LIMIT_STATES].limit /
+		    (PFSYNC_BULKPACKETS * sc->sc_maxcount));
+#endif
+#ifdef __FreeBSD__
+		if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
+		if (pf_status.debug >= PF_DEBUG_MISC)
+#endif
+			printf("pfsync: received bulk update start\n");
+		break;
+
+	case PFSYNC_BUS_END:
+		if (time_uptime - ntohl(bus->endtime) >=
+		    sc->sc_ureq_sent) {
+			/* that's it, we're happy */
+			sc->sc_ureq_sent = 0;
+			sc->sc_bulk_tries = 0;
+			timeout_del(&sc->sc_bulkfail_tmo);
 #if NCARP > 0
-				if (!pfsync_sync_ok)
+#ifdef notyet
 #ifdef __FreeBSD__
-#ifdef CARP_ADVANCED
-					carp_group_demote_adj(sc->sc_ifp, -1);
+			if (!sc->pfsync_sync_ok)
+#else
+			if (!pfsync_sync_ok)
+#endif
+				carp_group_demote_adj(&sc->sc_if, -1);
+#endif
 #endif
+#ifdef __FreeBSD__
+			sc->pfsync_sync_ok = 1;
 #else
-					carp_group_demote_adj(&sc->sc_if, -1);
+			pfsync_sync_ok = 1;
 #endif
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC)
 #endif
-				pfsync_sync_ok = 1;
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync: received valid "
-					    "bulk update end\n");
-			} else {
-				if (pf_status.debug >= PF_DEBUG_MISC)
-					printf("pfsync: received invalid "
-					    "bulk update end: bad timestamp\n");
-			}
-			break;
+				printf("pfsync: received valid "
+				    "bulk update end\n");
+		} else {
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC)
+#endif
+				printf("pfsync: received invalid "
+				    "bulk update end: bad timestamp\n");
 		}
 		break;
-#ifdef PFSYNC_TDB
-	case PFSYNC_ACT_TDB_UPD:
-		if ((mp = m_pulldown(m, iplen + sizeof(*ph),
-		    count * sizeof(*pt), &offp)) == NULL) {
-			pfsyncstats.pfsyncs_badlen++;
-			return;
-		}
-		s = splsoftnet();
+	}
+
+	return (len);
+}
+
+int
+pfsync_in_tdb(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	int len = count * sizeof(struct pfsync_tdb);
+
+#if defined(IPSEC)
+	struct pfsync_tdb *tp;
+	struct mbuf *mp;
+	int offp;
+	int i;
+	int s;
+
+	mp = m_pulldown(m, offset, len, &offp);
+	if (mp == NULL) {
+		V_pfsyncstats.pfsyncs_badlen++;
+		return (-1);
+	}
+	tp = (struct pfsync_tdb *)(mp->m_data + offp);
+
+	s = splsoftnet();
 #ifdef __FreeBSD__
-		PF_LOCK();
+	PF_LOCK();
 #endif
-		for (i = 0, pt = (struct pfsync_tdb *)(mp->m_data + offp);
-		    i < count; i++, pt++)
-			pfsync_update_net_tdb(pt);
+	for (i = 0; i < count; i++)
+		pfsync_update_net_tdb(&tp[i]);
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+	PF_UNLOCK();
 #endif
-		splx(s);
-		break;
+	splx(s);
 #endif
+
+	return (len);
+}
+
+#if defined(IPSEC)
+/* Update an in-kernel tdb. Silently fail if no tdb is found. */
+void
+pfsync_update_net_tdb(struct pfsync_tdb *pt)
+{
+	struct tdb		*tdb;
+	int			 s;
+
+	/* check for invalid values */
+	if (ntohl(pt->spi) <= SPI_RESERVED_MAX ||
+	    (pt->dst.sa.sa_family != AF_INET &&
+	     pt->dst.sa.sa_family != AF_INET6))
+		goto bad;
+
+	s = spltdb();
+	tdb = gettdb(pt->spi, &pt->dst, pt->sproto);
+	if (tdb) {
+		pt->rpl = ntohl(pt->rpl);
+		pt->cur_bytes = betoh64(pt->cur_bytes);
+
+		/* Neither replay nor byte counter should ever decrease. */
+		if (pt->rpl < tdb->tdb_rpl ||
+		    pt->cur_bytes < tdb->tdb_cur_bytes) {
+			splx(s);
+			goto bad;
+		}
+
+		tdb->tdb_rpl = pt->rpl;
+		tdb->tdb_cur_bytes = pt->cur_bytes;
 	}
+	splx(s);
+	return;
 
-done:
-	if (m)
-		m_freem(m);
+bad:
+#ifdef __FreeBSD__
+	if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
+	if (pf_status.debug >= PF_DEBUG_MISC)
+#endif
+		printf("pfsync_insert: PFSYNC_ACT_TDB_UPD: "
+		    "invalid value\n");
+	V_pfsyncstats.pfsyncs_badstate++;
+	return;
+}
+#endif
+
+
+int
+pfsync_in_eof(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	/* check if we are at the right place in the packet */
+	if (offset != m->m_pkthdr.len - sizeof(struct pfsync_eof))
+		V_pfsyncstats.pfsyncs_badact++;
+
+	/* we're done. free and let the caller return */
+	m_freem(m);
+	return (-1);
+}
+
+int
+pfsync_in_error(struct pfsync_pkt *pkt, struct mbuf *m, int offset, int count)
+{
+	V_pfsyncstats.pfsyncs_badact++;
+
+	m_freem(m);
+	return (-1);
 }
 
 int
 pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
-	struct route *ro)
+#ifdef __FreeBSD__
+	struct route *rt)
+#else
+	struct rtentry *rt)
+#endif
 {
 	m_freem(m);
 	return (0);
@@ -1101,12 +1779,15 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 	struct ip_moptions *imo = &sc->sc_imo;
 	struct pfsyncreq pfsyncr;
 	struct ifnet    *sifp;
+	struct ip *ip;
 	int s, error;
 
 	switch (cmd) {
+#if 0
 	case SIOCSIFADDR:
 	case SIOCAIFADDR:
 	case SIOCSIFDSTADDR:
+#endif
 	case SIOCSIFFLAGS:
 #ifdef __FreeBSD__
 		if (ifp->if_flags & IFF_UP)
@@ -1121,32 +1802,33 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 #endif
 		break;
 	case SIOCSIFMTU:
-		if (ifr->ifr_mtu < PFSYNC_MINMTU)
+		if (ifr->ifr_mtu <= PFSYNC_MINPKT)
 			return (EINVAL);
-		if (ifr->ifr_mtu > MCLBYTES)
+		if (ifr->ifr_mtu > MCLBYTES) /* XXX could be bigger */
 			ifr->ifr_mtu = MCLBYTES;
-		s = splnet();
+		if (ifr->ifr_mtu < ifp->if_mtu) {
+			s = splnet();
 #ifdef __FreeBSD__
-		PF_LOCK();
+			PF_LOCK();
 #endif
-		if (ifr->ifr_mtu < ifp->if_mtu)
-			pfsync_sendout(sc);
-		pfsync_setmtu(sc, ifr->ifr_mtu);
+			pfsync_sendout();
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+			PF_UNLOCK();
 #endif
-		splx(s);
+			splx(s);
+		}
+		ifp->if_mtu = ifr->ifr_mtu;
 		break;
 	case SIOCGETPFSYNC:
 		bzero(&pfsyncr, sizeof(pfsyncr));
-		if (sc->sc_sync_ifp)
+		if (sc->sc_sync_if) {
 			strlcpy(pfsyncr.pfsyncr_syncdev,
-			    sc->sc_sync_ifp->if_xname, IFNAMSIZ);
+			    sc->sc_sync_if->if_xname, IFNAMSIZ);
+		}
 		pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
 		pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
-		if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
-			return (error);
-		break;
+		return (copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr)));
+
 	case SIOCSETPFSYNC:
 #ifdef __FreeBSD__
 		if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
@@ -1182,20 +1864,13 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 		sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
 
 		if (pfsyncr.pfsyncr_syncdev[0] == 0) {
-			sc->sc_sync_ifp = NULL;
-			if (sc->sc_mbuf_net != NULL) {
-				/* Don't keep stale pfsync packets around. */
-				s = splnet();
-				m_freem(sc->sc_mbuf_net);
-				sc->sc_mbuf_net = NULL;
-				sc->sc_statep_net.s = NULL;
-				splx(s);
-			}
+			sc->sc_sync_if = NULL;
 #ifdef __FreeBSD__
 			PF_UNLOCK();
 #endif
 			if (imo->imo_num_memberships > 0) {
-				in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
+				in_delmulti(imo->imo_membership[
+				    --imo->imo_num_memberships]);
 				imo->imo_multicast_ifp = NULL;
 			}
 			break;
@@ -1206,27 +1881,21 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 #endif
 		if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL)
 			return (EINVAL);
+
 #ifdef __FreeBSD__
 		PF_LOCK();
 #endif
-
 		s = splnet();
 #ifdef __FreeBSD__
 		if (sifp->if_mtu < sc->sc_ifp->if_mtu ||
 #else
 		if (sifp->if_mtu < sc->sc_if.if_mtu ||
 #endif
-		    (sc->sc_sync_ifp != NULL &&
-		    sifp->if_mtu < sc->sc_sync_ifp->if_mtu) ||
+		    (sc->sc_sync_if != NULL &&
+		    sifp->if_mtu < sc->sc_sync_if->if_mtu) ||
 		    sifp->if_mtu < MCLBYTES - sizeof(struct ip))
-			pfsync_sendout(sc);
-		sc->sc_sync_ifp = sifp;
-
-#ifdef __FreeBSD__
-		pfsync_setmtu(sc, sc->sc_ifp->if_mtu);
-#else
-		pfsync_setmtu(sc, sc->sc_if.if_mtu);
-#endif
+			pfsync_sendout();
+		sc->sc_sync_if = sifp;
 
 		if (imo->imo_num_memberships > 0) {
 #ifdef __FreeBSD__
@@ -1239,7 +1908,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			imo->imo_multicast_ifp = NULL;
 		}
 
-		if (sc->sc_sync_ifp &&
+		if (sc->sc_sync_if &&
 #ifdef __FreeBSD__
 		    sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
 #else
@@ -1247,8 +1916,8 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 #endif
 			struct in_addr addr;
 
-			if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
-				sc->sc_sync_ifp = NULL;
+			if (!(sc->sc_sync_if->if_flags & IFF_MULTICAST)) {
+				sc->sc_sync_if = NULL;
 #ifdef __FreeBSD__
 				PF_UNLOCK();
 #endif
@@ -1266,8 +1935,8 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			PF_UNLOCK();
 #endif
 			if ((imo->imo_membership[0] =
-			    in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
-				sc->sc_sync_ifp = NULL;
+			    in_addmulti(&addr, sc->sc_sync_if)) == NULL) {
+				sc->sc_sync_if = NULL;
 				splx(s);
 				return (ENOBUFS);
 			}
@@ -1275,966 +1944,1359 @@ pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			PF_LOCK();
 #endif
 			imo->imo_num_memberships++;
-			imo->imo_multicast_ifp = sc->sc_sync_ifp;
+			imo->imo_multicast_ifp = sc->sc_sync_if;
 			imo->imo_multicast_ttl = PFSYNC_DFLTTL;
 			imo->imo_multicast_loop = 0;
 		}
 
-		if (sc->sc_sync_ifp ||
-#ifdef __FreeBSD__
-		    sc->sc_sendaddr.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
-#else
-		    sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
-#endif
+		ip = &sc->sc_template;
+		bzero(ip, sizeof(*ip));
+		ip->ip_v = IPVERSION;
+		ip->ip_hl = sizeof(sc->sc_template) >> 2;
+		ip->ip_tos = IPTOS_LOWDELAY;
+		/* len and id are set later */
+		ip->ip_off = htons(IP_DF);
+		ip->ip_ttl = PFSYNC_DFLTTL;
+		ip->ip_p = IPPROTO_PFSYNC;
+		ip->ip_src.s_addr = INADDR_ANY;
+		ip->ip_dst.s_addr = sc->sc_sync_peer.s_addr;
+
+		if (sc->sc_sync_if) {
 			/* Request a full state table update. */
 			sc->sc_ureq_sent = time_uptime;
 #if NCARP > 0
+#ifdef notyet
+#ifdef __FreeBSD__
+			if (sc->pfsync_sync_ok)
+#else
 			if (pfsync_sync_ok)
+#endif
+				carp_group_demote_adj(&sc->sc_if, 1);
+#endif
+#endif
+#ifdef __FreeBSD__
+			sc->pfsync_sync_ok = 0;
+#else
+			pfsync_sync_ok = 0;
+#endif
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC)
+#endif
+				printf("pfsync: requesting bulk update\n");
+#ifdef __FreeBSD__
+				callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
+				    pfsync_bulk_fail, V_pfsyncif);
+#else
+			timeout_add_sec(&sc->sc_bulkfail_tmo, 5);
+#endif
+			pfsync_request_update(0, 0);
+		}
+#ifdef __FreeBSD__
+		PF_UNLOCK();
+#endif
+		splx(s);
+
+		break;
+
+	default:
+		return (ENOTTY);
+	}
+
+	return (0);
+}
+
+int
+pfsync_out_state(struct pf_state *st, struct mbuf *m, int offset)
+{
+	struct pfsync_state *sp = (struct pfsync_state *)(m->m_data + offset);
+
+	pfsync_state_export(sp, st);
+
+	return (sizeof(*sp));
+}
+
+int
+pfsync_out_iack(struct pf_state *st, struct mbuf *m, int offset)
+{
+	struct pfsync_ins_ack *iack =
+	    (struct pfsync_ins_ack *)(m->m_data + offset);
+
+	iack->id = st->id;
+	iack->creatorid = st->creatorid;
+
+	return (sizeof(*iack));
+}
+
+int
+pfsync_out_upd_c(struct pf_state *st, struct mbuf *m, int offset)
+{
+	struct pfsync_upd_c *up = (struct pfsync_upd_c *)(m->m_data + offset);
+
+	up->id = st->id;
+	pf_state_peer_hton(&st->src, &up->src);
+	pf_state_peer_hton(&st->dst, &up->dst);
+	up->creatorid = st->creatorid;
+
+	up->expire = pf_state_expires(st);
+	if (up->expire <= time_second)
+		up->expire = htonl(0);
+	else
+		up->expire = htonl(up->expire - time_second);
+	up->timeout = st->timeout;
+
+	bzero(up->_pad, sizeof(up->_pad)); /* XXX */
+
+	return (sizeof(*up));
+}
+
+int
+pfsync_out_del(struct pf_state *st, struct mbuf *m, int offset)
+{
+	struct pfsync_del_c *dp = (struct pfsync_del_c *)(m->m_data + offset);
+
+	dp->id = st->id;
+	dp->creatorid = st->creatorid;
+
+	SET(st->state_flags, PFSTATE_NOSYNC);
+
+	return (sizeof(*dp));
+}
+
+void
+pfsync_drop(struct pfsync_softc *sc)
+{
+	struct pf_state *st;
+	struct pfsync_upd_req_item *ur;
+#ifdef notyet
+	struct tdb *t;
+#endif
+	int q;
+
+	for (q = 0; q < PFSYNC_S_COUNT; q++) {
+		if (TAILQ_EMPTY(&sc->sc_qs[q]))
+			continue;
+
+		TAILQ_FOREACH(st, &sc->sc_qs[q], sync_list) {
+#ifdef PFSYNC_DEBUG
+#ifdef __FreeBSD__
+			KASSERT(st->sync_state == q,
+				("%s: st->sync_state == q", 
+					__FUNCTION__));
+#else
+			KASSERT(st->sync_state == q);
+#endif
+#endif
+			st->sync_state = PFSYNC_S_NONE;
+		}
+		TAILQ_INIT(&sc->sc_qs[q]);
+	}
+
+	while ((ur = TAILQ_FIRST(&sc->sc_upd_req_list)) != NULL) {
+		TAILQ_REMOVE(&sc->sc_upd_req_list, ur, ur_entry);
+		pool_put(&sc->sc_pool, ur);
+	}
+
+	sc->sc_plus = NULL;
+
+#ifdef notyet
+	if (!TAILQ_EMPTY(&sc->sc_tdb_q)) {
+		TAILQ_FOREACH(t, &sc->sc_tdb_q, tdb_sync_entry)
+			CLR(t->tdb_flags, TDBF_PFSYNC);
+
+		TAILQ_INIT(&sc->sc_tdb_q);
+	}
+#endif
+
+	sc->sc_len = PFSYNC_MINPKT;
+}
+
+void
+pfsync_sendout(void)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+	struct ifnet *ifp = sc->sc_ifp;
+#else
+	struct ifnet *ifp = &sc->sc_if;
+#endif
+	struct mbuf *m;
+#endif
+	struct ip *ip;
+	struct pfsync_header *ph;
+	struct pfsync_subheader *subh;
+	struct pf_state *st;
+	struct pfsync_upd_req_item *ur;
+#ifdef notyet
+	struct tdb *t;
+#endif
+#ifdef __FreeBSD__
+	size_t pktlen;
+#endif
+	int offset;
+	int q, count = 0;
+
+#ifdef __FreeBSD__
+	PF_ASSERT(MA_OWNED);
+#else
+	splassert(IPL_NET);
+#endif
+
+	if (sc == NULL || sc->sc_len == PFSYNC_MINPKT)
+		return;
+
+#if NBPFILTER > 0
+	if (ifp->if_bpf == NULL && sc->sc_sync_if == NULL) {
+#else
+	if (sc->sc_sync_if == NULL) {
+#endif
+		pfsync_drop(sc);
+		return;
+	}
+
+	MGETHDR(m, M_DONTWAIT, MT_DATA);
+	if (m == NULL) {
+#ifdef __FreeBSD__
+		sc->sc_ifp->if_oerrors++;
+#else
+		sc->sc_if.if_oerrors++;
+#endif
+		V_pfsyncstats.pfsyncs_onomem++;
+		pfsync_drop(sc);
+		return;
+	}
+
+#ifdef __FreeBSD__
+	pktlen = max_linkhdr + sc->sc_len;
+	if (pktlen > MHLEN) {
+		/* Find the right pool to allocate from. */
+		/* XXX: This is ugly. */
+		m_cljget(m, M_DONTWAIT, pktlen <= MSIZE ? MSIZE :
+			pktlen <= MCLBYTES ? MCLBYTES :
+#if MJUMPAGESIZE != MCLBYTES
+			pktlen <= MJUMPAGESIZE ? MJUMPAGESIZE :
+#endif
+			pktlen <= MJUM9BYTES ? MJUM9BYTES : MJUM16BYTES);
+#else
+	if (max_linkhdr + sc->sc_len > MHLEN) {
+		MCLGETI(m, M_DONTWAIT, NULL, max_linkhdr + sc->sc_len);
+#endif
+		if (!ISSET(m->m_flags, M_EXT)) {
+			m_free(m);
+#ifdef __FreeBSD__
+			sc->sc_ifp->if_oerrors++;
+#else
+			sc->sc_if.if_oerrors++;
+#endif
+			V_pfsyncstats.pfsyncs_onomem++;
+			pfsync_drop(sc);
+			return;
+		}
+	}
+	m->m_data += max_linkhdr;
+	m->m_len = m->m_pkthdr.len = sc->sc_len;
+
+	/* build the ip header */
+	ip = (struct ip *)m->m_data;
+	bcopy(&sc->sc_template, ip, sizeof(*ip));
+	offset = sizeof(*ip);
+
+	ip->ip_len = htons(m->m_pkthdr.len);
+	ip->ip_id = htons(ip_randomid());
+
+	/* build the pfsync header */
+	ph = (struct pfsync_header *)(m->m_data + offset);
+	bzero(ph, sizeof(*ph));
+	offset += sizeof(*ph);
+
+	ph->version = PFSYNC_VERSION;
+	ph->len = htons(sc->sc_len - sizeof(*ip));
+#ifdef __FreeBSD__
+	bcopy(V_pf_status.pf_chksum, ph->pfcksum, PF_MD5_DIGEST_LENGTH);
+#else
+	bcopy(pf_status.pf_chksum, ph->pfcksum, PF_MD5_DIGEST_LENGTH);
+#endif
+
+	/* walk the queues */
+	for (q = 0; q < PFSYNC_S_COUNT; q++) {
+		if (TAILQ_EMPTY(&sc->sc_qs[q]))
+			continue;
+
+		subh = (struct pfsync_subheader *)(m->m_data + offset);
+		offset += sizeof(*subh);
+
+		count = 0;
+		TAILQ_FOREACH(st, &sc->sc_qs[q], sync_list) {
+#ifdef PFSYNC_DEBUG
+#ifdef __FreeBSD__
+			KASSERT(st->sync_state == q,
+				("%s: st->sync_state == q",
+					__FUNCTION__));
+#else
+			KASSERT(st->sync_state == q);
+#endif
+#endif
+
+			offset += pfsync_qs[q].write(st, m, offset);
+			st->sync_state = PFSYNC_S_NONE;
+			count++;
+		}
+		TAILQ_INIT(&sc->sc_qs[q]);
+
+		bzero(subh, sizeof(*subh));
+		subh->action = pfsync_qs[q].action;
+		subh->count = htons(count);
+	}
+
+	if (!TAILQ_EMPTY(&sc->sc_upd_req_list)) {
+		subh = (struct pfsync_subheader *)(m->m_data + offset);
+		offset += sizeof(*subh);
+
+		count = 0;
+		while ((ur = TAILQ_FIRST(&sc->sc_upd_req_list)) != NULL) {
+			TAILQ_REMOVE(&sc->sc_upd_req_list, ur, ur_entry);
+
+			bcopy(&ur->ur_msg, m->m_data + offset,
+			    sizeof(ur->ur_msg));
+			offset += sizeof(ur->ur_msg);
+
+			pool_put(&sc->sc_pool, ur);
+
+			count++;
+		}
+
+		bzero(subh, sizeof(*subh));
+		subh->action = PFSYNC_ACT_UPD_REQ;
+		subh->count = htons(count);
+	}
+
+	/* has someone built a custom region for us to add? */
+	if (sc->sc_plus != NULL) {
+		bcopy(sc->sc_plus, m->m_data + offset, sc->sc_pluslen);
+		offset += sc->sc_pluslen;
+
+		sc->sc_plus = NULL;
+	}
+
+#ifdef notyet
+	if (!TAILQ_EMPTY(&sc->sc_tdb_q)) {
+		subh = (struct pfsync_subheader *)(m->m_data + offset);
+		offset += sizeof(*subh);
+
+		count = 0;
+		TAILQ_FOREACH(t, &sc->sc_tdb_q, tdb_sync_entry) {
+			offset += pfsync_out_tdb(t, m, offset);
+			CLR(t->tdb_flags, TDBF_PFSYNC);
+
+			count++;
+		}
+		TAILQ_INIT(&sc->sc_tdb_q);
+
+		bzero(subh, sizeof(*subh));
+		subh->action = PFSYNC_ACT_TDB;
+		subh->count = htons(count);
+	}
+#endif
+
+	subh = (struct pfsync_subheader *)(m->m_data + offset);
+	offset += sizeof(*subh);
+
+	bzero(subh, sizeof(*subh));
+	subh->action = PFSYNC_ACT_EOF;
+	subh->count = htons(1);
+
+	/* XXX write checksum in EOF here */
+
+	/* we're done, let's put it on the wire */
+#if NBPFILTER > 0
+	if (ifp->if_bpf) {
+		m->m_data += sizeof(*ip);
+		m->m_len = m->m_pkthdr.len = sc->sc_len - sizeof(*ip);
+#ifdef __FreeBSD__
+		BPF_MTAP(ifp, m);
+#else
+		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+		m->m_data -= sizeof(*ip);
+		m->m_len = m->m_pkthdr.len = sc->sc_len;
+	}
+
+	if (sc->sc_sync_if == NULL) {
+		sc->sc_len = PFSYNC_MINPKT;
+		m_freem(m);
+		return;
+	}
+#endif
+
+#ifdef __FreeBSD__
+	sc->sc_ifp->if_opackets++;
+	sc->sc_ifp->if_obytes += m->m_pkthdr.len;
+#else
+	sc->sc_if.if_opackets++;
+	sc->sc_if.if_obytes += m->m_pkthdr.len;
+#endif
+
+#ifdef __FreeBSD__
+	PF_UNLOCK();
+#endif
+	if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL) == 0)
+#ifdef __FreeBSD__
+	{
+		PF_LOCK();
+#endif
+		V_pfsyncstats.pfsyncs_opackets++;
+#ifdef __FreeBSD__
+	}
+#endif
+	else
+#ifdef __FreeBSD__
+	{
+		PF_LOCK();
+#endif
+		V_pfsyncstats.pfsyncs_oerrors++;
+#ifdef __FreeBSD__
+	}
+#endif
+
+	/* start again */
+	sc->sc_len = PFSYNC_MINPKT;
+}
+
+void
+pfsync_insert_state(struct pf_state *st)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+
+#ifdef __FreeBSD__
+	PF_ASSERT(MA_OWNED);
+#else
+	splassert(IPL_SOFTNET);
+#endif
+
+	if (ISSET(st->rule.ptr->rule_flag, PFRULE_NOSYNC) ||
+	    st->key[PF_SK_WIRE]->proto == IPPROTO_PFSYNC) {
+		SET(st->state_flags, PFSTATE_NOSYNC);
+		return;
+	}
+
+	if (sc == NULL || ISSET(st->state_flags, PFSTATE_NOSYNC))
+		return;
+
+#ifdef PFSYNC_DEBUG
+#ifdef __FreeBSD__
+	KASSERT(st->sync_state == PFSYNC_S_NONE,
+		("%s: st->sync_state == PFSYNC_S_NONE", __FUNCTION__));
+#else
+	KASSERT(st->sync_state == PFSYNC_S_NONE);
+#endif
+#endif
+
+	if (sc->sc_len == PFSYNC_MINPKT)
+#ifdef __FreeBSD__
+		callout_reset(&sc->sc_tmo, 1 * hz, pfsync_timeout,
+		    V_pfsyncif);
+#else
+		timeout_add_sec(&sc->sc_tmo, 1);
+#endif
+
+	pfsync_q_ins(st, PFSYNC_S_INS);
+
+	if (ISSET(st->state_flags, PFSTATE_ACK))
+		schednetisr(NETISR_PFSYNC);
+	else
+		st->sync_updates = 0;
+}
+
+int defer = 10;
+
+int
+pfsync_defer(struct pf_state *st, struct mbuf *m)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+	struct pfsync_deferral *pd;
+
+#ifdef __FreeBSD__
+	PF_ASSERT(MA_OWNED);
+#else
+	splassert(IPL_SOFTNET);
+#endif
+
+	if (sc->sc_deferred >= 128)
+		pfsync_undefer(TAILQ_FIRST(&sc->sc_deferrals), 0);
+
+	pd = pool_get(&sc->sc_pool, M_NOWAIT);
+	if (pd == NULL)
+		return (0);
+	sc->sc_deferred++;
+
+#ifdef __FreeBSD__
+	m->m_flags |= M_SKIP_FIREWALL;
+#else
+	m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
+#endif
+	SET(st->state_flags, PFSTATE_ACK);
+
+	pd->pd_st = st;
+	pd->pd_m = m;
+
+	TAILQ_INSERT_TAIL(&sc->sc_deferrals, pd, pd_entry);
+#ifdef __FreeBSD__
+	callout_init(&pd->pd_tmo, CALLOUT_MPSAFE);
+	callout_reset(&pd->pd_tmo, defer, pfsync_defer_tmo,
+		pd);
+#else
+	timeout_set(&pd->pd_tmo, pfsync_defer_tmo, pd);
+	timeout_add(&pd->pd_tmo, defer);
+#endif
+
+	return (1);
+}
+
+void
+pfsync_undefer(struct pfsync_deferral *pd, int drop)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+	int s;
+
+#ifdef __FreeBSD__
+	PF_ASSERT(MA_OWNED);
+#else
+	splassert(IPL_SOFTNET);
+#endif
+
+	TAILQ_REMOVE(&sc->sc_deferrals, pd, pd_entry);
+	sc->sc_deferred--;
+
+	CLR(pd->pd_st->state_flags, PFSTATE_ACK);
+	timeout_del(&pd->pd_tmo); /* bah */
+	if (drop)
+		m_freem(pd->pd_m);
+	else {
+		s = splnet();
+#ifdef __FreeBSD__
+		/* XXX: use pf_defered?! */
+		PF_UNLOCK();
+#endif
+		ip_output(pd->pd_m, (void *)NULL, (void *)NULL, 0,
+		    (void *)NULL, (void *)NULL);
+#ifdef __FreeBSD__
+		PF_LOCK();
+#endif
+		splx(s);
+	}
+
+	pool_put(&sc->sc_pool, pd);
+}
+
+void
+pfsync_defer_tmo(void *arg)
+{
+#if defined(__FreeBSD__) && defined(VIMAGE)
+	struct pfsync_deferral *pd = arg;
+#endif
+	int s;
+
+	s = splsoftnet();
+#ifdef __FreeBSD__
+	CURVNET_SET(pd->pd_m->m_pkthdr.rcvif->if_vnet); /* XXX */
+	PF_LOCK();
+#endif
+	pfsync_undefer(arg, 0);
+#ifdef __FreeBSD__
+	PF_UNLOCK();
+	CURVNET_RESTORE();
+#endif
+	splx(s);
+}
+
+void
+pfsync_deferred(struct pf_state *st, int drop)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+	struct pfsync_deferral *pd;
+
+	TAILQ_FOREACH(pd, &sc->sc_deferrals, pd_entry) {
+		 if (pd->pd_st == st) {
+			pfsync_undefer(pd, drop);
+			return;
+		}
+	}
+
+	panic("pfsync_send_deferred: unable to find deferred state");
+}
+
+u_int pfsync_upds = 0;
+
+void
+pfsync_update_state(struct pf_state *st)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+	int sync = 0;
+
+#ifdef __FreeBSD__
+	PF_ASSERT(MA_OWNED);
+#else
+	splassert(IPL_SOFTNET);
+#endif
+
+	if (sc == NULL)
+		return;
+
+	if (ISSET(st->state_flags, PFSTATE_ACK))
+		pfsync_deferred(st, 0);
+	if (ISSET(st->state_flags, PFSTATE_NOSYNC)) {
+		if (st->sync_state != PFSYNC_S_NONE)
+			pfsync_q_del(st);
+		return;
+	}
+
+	if (sc->sc_len == PFSYNC_MINPKT)
+#ifdef __FreeBSD__
+		callout_reset(&sc->sc_tmo, 1 * hz, pfsync_timeout,
+		    V_pfsyncif);
+#else
+		timeout_add_sec(&sc->sc_tmo, 1);
+#endif
+
+	switch (st->sync_state) {
+	case PFSYNC_S_UPD_C:
+	case PFSYNC_S_UPD:
+	case PFSYNC_S_INS:
+		/* we're already handling it */
+
+		st->sync_updates++;
+		if (st->sync_updates >= sc->sc_maxupdates)
+			sync = 1;
+		break;
+
+	case PFSYNC_S_IACK:
+		pfsync_q_del(st);
+	case PFSYNC_S_NONE:
+		pfsync_q_ins(st, PFSYNC_S_UPD_C);
+		st->sync_updates = 0;
+		break;
+
+	default:
+		panic("pfsync_update_state: unexpected sync state %d",
+		    st->sync_state);
+	}
+
+	if (sync || (time_second - st->pfsync_time) < 2) {
+		pfsync_upds++;
+		schednetisr(NETISR_PFSYNC);
+	}
+}
+
+void
+pfsync_request_update(u_int32_t creatorid, u_int64_t id)
+{
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
+	struct pfsync_upd_req_item *item;
+	size_t nlen = sizeof(struct pfsync_upd_req);
+	int s;
+
+	/*
+	 * this code does nothing to prevent multiple update requests for the
+	 * same state being generated.
+	 */
+
+	item = pool_get(&sc->sc_pool, PR_NOWAIT);
+	if (item == NULL) {
+		/* XXX stats */
+		return;
+	}
+
+	item->ur_msg.id = id;
+	item->ur_msg.creatorid = creatorid;
+
+	if (TAILQ_EMPTY(&sc->sc_upd_req_list))
+		nlen += sizeof(struct pfsync_subheader);
+
+#ifdef __FreeBSD__
+	if (sc->sc_len + nlen > sc->sc_ifp->if_mtu) {
+#else
+	if (sc->sc_len + nlen > sc->sc_if.if_mtu) {
+#endif
+		s = splnet();
+		pfsync_sendout();
+		splx(s);
+
+		nlen = sizeof(struct pfsync_subheader) +
+		    sizeof(struct pfsync_upd_req);
+	}
+
+	TAILQ_INSERT_TAIL(&sc->sc_upd_req_list, item, ur_entry);
+	sc->sc_len += nlen;
+
+	schednetisr(NETISR_PFSYNC);
+}
+
+void
+pfsync_update_state_req(struct pf_state *st)
+{
 #ifdef __FreeBSD__
-#ifdef CARP_ADVANCED
-				carp_group_demote_adj(sc->sc_ifp, 1);
-#endif
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-				carp_group_demote_adj(&sc->sc_if, 1);
-#endif
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-			pfsync_sync_ok = 0;
-			if (pf_status.debug >= PF_DEBUG_MISC)
-				printf("pfsync: requesting bulk update\n");
+
+	if (sc == NULL)
+		panic("pfsync_update_state_req: nonexistant instance");
+
+	if (ISSET(st->state_flags, PFSTATE_NOSYNC)) {
+		if (st->sync_state != PFSYNC_S_NONE)
+			pfsync_q_del(st);
+		return;
+	}
+
+	switch (st->sync_state) {
+	case PFSYNC_S_UPD_C:
+	case PFSYNC_S_IACK:
+		pfsync_q_del(st);
+	case PFSYNC_S_NONE:
+		pfsync_q_ins(st, PFSYNC_S_UPD);
+		schednetisr(NETISR_PFSYNC);
+		return;
+
+	case PFSYNC_S_INS:
+	case PFSYNC_S_UPD:
+	case PFSYNC_S_DEL:
+		/* we're already handling it */
+		return;
+
+	default:
+		panic("pfsync_update_state_req: unexpected sync state %d",
+		    st->sync_state);
+	}
+}
+
+void
+pfsync_delete_state(struct pf_state *st)
+{
 #ifdef __FreeBSD__
-			callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
-			    pfsync_bulkfail, pfsyncif);
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-			timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-			error = pfsync_request_update(NULL, NULL);
-			if (error == ENOMEM) {
+
 #ifdef __FreeBSD__
-				PF_UNLOCK();
+	PF_ASSERT(MA_OWNED);
+#else
+	splassert(IPL_SOFTNET);
 #endif
-				splx(s);
-				return (ENOMEM);
-			}
-			pfsync_sendout(sc);
-		}
+
+	if (sc == NULL)
+		return;
+
+	if (ISSET(st->state_flags, PFSTATE_ACK))
+		pfsync_deferred(st, 1);
+	if (ISSET(st->state_flags, PFSTATE_NOSYNC)) {
+		if (st->sync_state != PFSYNC_S_NONE)
+			pfsync_q_del(st);
+		return;
+	}
+
+	if (sc->sc_len == PFSYNC_MINPKT)
 #ifdef __FreeBSD__
-		PF_UNLOCK();
+		callout_reset(&sc->sc_tmo, 1 * hz, pfsync_timeout,
+		    V_pfsyncif);
+#else
+		timeout_add_sec(&sc->sc_tmo, 1);
 #endif
-		splx(s);
 
-		break;
+	switch (st->sync_state) {
+	case PFSYNC_S_INS:
+		/* we never got to tell the world so just forget about it */
+		pfsync_q_del(st);
+		return;
+
+	case PFSYNC_S_UPD_C:
+	case PFSYNC_S_UPD:
+	case PFSYNC_S_IACK:
+		pfsync_q_del(st);
+		/* FALLTHROUGH to putting it on the del list */
+
+	case PFSYNC_S_NONE:
+		pfsync_q_ins(st, PFSYNC_S_DEL);
+		return;
 
 	default:
-		return (ENOTTY);
+		panic("pfsync_delete_state: unexpected sync state %d",
+		    st->sync_state);
 	}
-
-	return (0);
 }
 
 void
-pfsync_setmtu(struct pfsync_softc *sc, int mtu_req)
+pfsync_clear_states(u_int32_t creatorid, const char *ifname)
 {
-	int mtu;
+	struct {
+		struct pfsync_subheader subh;
+		struct pfsync_clr clr;
+	} __packed r;
 
-	if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req)
-		mtu = sc->sc_sync_ifp->if_mtu;
-	else
-		mtu = mtu_req;
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
 
-	sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) /
-	    sizeof(struct pfsync_state);
-	if (sc->sc_maxcount > 254)
-	    sc->sc_maxcount = 254;
 #ifdef __FreeBSD__
-	sc->sc_ifp->if_mtu = sizeof(struct pfsync_header) +
+	PF_ASSERT(MA_OWNED);
 #else
-	sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
+	splassert(IPL_SOFTNET);
 #endif
-	    sc->sc_maxcount * sizeof(struct pfsync_state);
+
+	if (sc == NULL)
+		return;
+
+	bzero(&r, sizeof(r));
+
+	r.subh.action = PFSYNC_ACT_CLR;
+	r.subh.count = htons(1);
+
+	strlcpy(r.clr.ifname, ifname, sizeof(r.clr.ifname));
+	r.clr.creatorid = creatorid;
+
+	pfsync_send_plus(&r, sizeof(r));
 }
 
-struct mbuf *
-pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
+void
+pfsync_q_ins(struct pf_state *st, int q)
 {
-	struct pfsync_header *h;
-	struct mbuf *m;
-	int len;
-
-	MGETHDR(m, M_DONTWAIT, MT_DATA);
-	if (m == NULL) {
 #ifdef __FreeBSD__
-		sc->sc_ifp->if_oerrors++;
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-		sc->sc_if.if_oerrors++;
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-		return (NULL);
-	}
+	size_t nlen = pfsync_qs[q].len;
+	int s;
 
-	switch (action) {
-	case PFSYNC_ACT_CLR:
-		len = sizeof(struct pfsync_header) +
-		    sizeof(struct pfsync_state_clr);
-		break;
-	case PFSYNC_ACT_UPD_C:
-		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) +
-		    sizeof(struct pfsync_header);
-		break;
-	case PFSYNC_ACT_DEL_C:
-		len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) +
-		    sizeof(struct pfsync_header);
-		break;
-	case PFSYNC_ACT_UREQ:
-		len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) +
-		    sizeof(struct pfsync_header);
-		break;
-	case PFSYNC_ACT_BUS:
-		len = sizeof(struct pfsync_header) +
-		    sizeof(struct pfsync_state_bus);
-		break;
-#ifdef PFSYNC_TDB
-	case PFSYNC_ACT_TDB_UPD:
-		len = (sc->sc_maxcount * sizeof(struct pfsync_tdb)) +
-		    sizeof(struct pfsync_header);
-		break;
+#ifdef __FreeBSD__
+	KASSERT(st->sync_state == PFSYNC_S_NONE,
+		("%s: st->sync_state == PFSYNC_S_NONE", __FUNCTION__));
+#else
+	KASSERT(st->sync_state == PFSYNC_S_NONE);
 #endif
-	default:
-		len = (sc->sc_maxcount * sizeof(struct pfsync_state)) +
-		    sizeof(struct pfsync_header);
-		break;
-	}
 
-	if (len > MHLEN) {
-		MCLGET(m, M_DONTWAIT);
-		if ((m->m_flags & M_EXT) == 0) {
-			m_free(m);
+#if 1 || defined(PFSYNC_DEBUG)
+	if (sc->sc_len < PFSYNC_MINPKT)
 #ifdef __FreeBSD__
-			sc->sc_ifp->if_oerrors++;
+		panic("pfsync pkt len is too low %zu", sc->sc_len);
 #else
-			sc->sc_if.if_oerrors++;
+		panic("pfsync pkt len is too low %d", sc->sc_len);
 #endif
-			return (NULL);
-		}
-		m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1);
-	} else
-		MH_ALIGN(m, len);
-
-	m->m_pkthdr.rcvif = NULL;
-	m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header);
-	h = mtod(m, struct pfsync_header *);
-	h->version = PFSYNC_VERSION;
-	h->af = 0;
-	h->count = 0;
-	h->action = action;
-#ifndef PFSYNC_TDB
-	if (action != PFSYNC_ACT_TDB_UPD)
 #endif
-		bcopy(&pf_status.pf_chksum, &h->pf_chksum,
-		    PF_MD5_DIGEST_LENGTH);
+	if (TAILQ_EMPTY(&sc->sc_qs[q]))
+		nlen += sizeof(struct pfsync_subheader);
 
-	*sp = (void *)((char *)h + PFSYNC_HDRLEN);
-#ifdef PFSYNC_TDB
-	if (action == PFSYNC_ACT_TDB_UPD)
 #ifdef __FreeBSD__
-		callout_reset(&sc->sc_tdb_tmo, hz, pfsync_tdb_timeout,
-		    pfsyncif);
+	if (sc->sc_len + nlen > sc->sc_ifp->if_mtu) {
 #else
-		timeout_add(&sc->sc_tdb_tmo, hz);
+	if (sc->sc_len + nlen > sc->sc_if.if_mtu) {
 #endif
-	else
+		s = splnet();
+#ifdef __FreeBSD__
+		PF_LOCK();
 #endif
+		pfsync_sendout();
 #ifdef __FreeBSD__
-		callout_reset(&sc->sc_tmo, hz, pfsync_timeout, pfsyncif);
-#else
-		timeout_add(&sc->sc_tmo, hz);
+		PF_UNLOCK();
 #endif
-	return (m);
+		splx(s);
+
+		nlen = sizeof(struct pfsync_subheader) + pfsync_qs[q].len;
+	}
+
+	sc->sc_len += nlen;
+	TAILQ_INSERT_TAIL(&sc->sc_qs[q], st, sync_list);
+	st->sync_state = q;
 }
 
-int
-pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
+void
+pfsync_q_del(struct pf_state *st)
 {
-	struct ifnet *ifp = NULL;
-	struct pfsync_softc *sc = pfsyncif;
-	struct pfsync_header *h, *h_net;
-	struct pfsync_state *sp = NULL;
-	struct pfsync_state_upd *up = NULL;
-	struct pfsync_state_del *dp = NULL;
-	struct pf_rule *r;
-	u_long secs;
-	int s, ret = 0;
-	u_int8_t i = 255, newaction = 0;
-
-	if (sc == NULL)
-		return (0);
 #ifdef __FreeBSD__
-	ifp = sc->sc_ifp;
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-	ifp = &sc->sc_if;
+	struct pfsync_softc *sc = pfsyncif;
 #endif
+	int q = st->sync_state;
 
-	/*
-	 * If a packet falls in the forest and there's nobody around to
-	 * hear, does it make a sound?
-	 */
-	if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
 #ifdef __FreeBSD__
-	    sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
+	KASSERT(st->sync_state != PFSYNC_S_NONE, 
+		("%s: st->sync_state != PFSYNC_S_NONE", __FUNCTION__));
 #else
-	    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
+	KASSERT(st->sync_state != PFSYNC_S_NONE);
 #endif
-		/* Don't leave any stale pfsync packets hanging around. */
-		if (sc->sc_mbuf != NULL) {
-			m_freem(sc->sc_mbuf);
-			sc->sc_mbuf = NULL;
-			sc->sc_statep.s = NULL;
-		}
-		return (0);
-	}
 
-	if (action >= PFSYNC_ACT_MAX)
-		return (EINVAL);
+	sc->sc_len -= pfsync_qs[q].len;
+	TAILQ_REMOVE(&sc->sc_qs[q], st, sync_list);
+	st->sync_state = PFSYNC_S_NONE;
 
-	s = splnet();
+	if (TAILQ_EMPTY(&sc->sc_qs[q]))
+		sc->sc_len -= sizeof(struct pfsync_subheader);
+}
+
+#ifdef notyet
+void
+pfsync_update_tdb(struct tdb *t, int output)
+{
 #ifdef __FreeBSD__
-	PF_ASSERT(MA_OWNED);
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-	if (sc->sc_mbuf == NULL) {
-		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
-		    (void *)&sc->sc_statep.s)) == NULL) {
-			splx(s);
-			return (ENOMEM);
-		}
-		h = mtod(sc->sc_mbuf, struct pfsync_header *);
-	} else {
-		h = mtod(sc->sc_mbuf, struct pfsync_header *);
-		if (h->action != action) {
-			pfsync_sendout(sc);
-			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
-			    (void *)&sc->sc_statep.s)) == NULL) {
-				splx(s);
-				return (ENOMEM);
-			}
-			h = mtod(sc->sc_mbuf, struct pfsync_header *);
-		} else {
-			/*
-			 * If it's an update, look in the packet to see if
-			 * we already have an update for the state.
-			 */
-			if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) {
-				struct pfsync_state *usp =
-				    (void *)((char *)h + PFSYNC_HDRLEN);
-
-				for (i = 0; i < h->count; i++) {
-					if (!memcmp(usp->id, &st->id,
-					    PFSYNC_ID_LEN) &&
-					    usp->creatorid == st->creatorid) {
-						sp = usp;
-						sp->updates++;
-						break;
-					}
-					usp++;
-				}
-			}
-		}
-	}
-
-	secs = time_second;
-
-	st->pfsync_time = time_uptime;
-
-	if (sp == NULL) {
-		/* not a "duplicate" update */
-		i = 255;
-		sp = sc->sc_statep.s++;
-		sc->sc_mbuf->m_pkthdr.len =
-		    sc->sc_mbuf->m_len += sizeof(struct pfsync_state);
-		h->count++;
-		bzero(sp, sizeof(*sp));
-
-		bcopy(&st->id, sp->id, sizeof(sp->id));
-		sp->creatorid = st->creatorid;
-
-		strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
-		pf_state_host_hton(&st->lan, &sp->lan);
-		pf_state_host_hton(&st->gwy, &sp->gwy);
-		pf_state_host_hton(&st->ext, &sp->ext);
-
-		bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
-
-		sp->creation = htonl(secs - st->creation);
-		pf_state_counter_hton(st->packets[0], sp->packets[0]);
-		pf_state_counter_hton(st->packets[1], sp->packets[1]);
-		pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
-		pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
-		if ((r = st->rule.ptr) == NULL)
-			sp->rule = htonl(-1);
-		else
-			sp->rule = htonl(r->nr);
-		if ((r = st->anchor.ptr) == NULL)
-			sp->anchor = htonl(-1);
-		else
-			sp->anchor = htonl(r->nr);
-		sp->af = st->af;
-		sp->proto = st->proto;
-		sp->direction = st->direction;
-		sp->log = st->log;
-		sp->state_flags = st->state_flags;
-		sp->timeout = st->timeout;
+	size_t nlen = sizeof(struct pfsync_tdb);
+	int s;
 
-		if (flags & PFSYNC_FLAG_STALE)
-			sp->sync_flags |= PFSTATE_STALE;
-	}
+	if (sc == NULL)
+		return;
 
-	pf_state_peer_hton(&st->src, &sp->src);
-	pf_state_peer_hton(&st->dst, &sp->dst);
+	if (!ISSET(t->tdb_flags, TDBF_PFSYNC)) {
+		if (TAILQ_EMPTY(&sc->sc_tdb_q))
+			nlen += sizeof(struct pfsync_subheader);
 
-	if (st->expire <= secs)
-		sp->expire = htonl(0);
-	else
-		sp->expire = htonl(st->expire - secs);
+		if (sc->sc_len + nlen > sc->sc_if.if_mtu) {
+			s = splnet();
+			pfsync_sendout();
+			splx(s);
 
-	/* do we need to build "compressed" actions for network transfer? */
-	if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
-		switch (action) {
-		case PFSYNC_ACT_UPD:
-			newaction = PFSYNC_ACT_UPD_C;
-			break;
-		case PFSYNC_ACT_DEL:
-			newaction = PFSYNC_ACT_DEL_C;
-			break;
-		default:
-			/* by default we just send the uncompressed states */
-			break;
+			nlen = sizeof(struct pfsync_subheader) +
+			    sizeof(struct pfsync_tdb);
 		}
-	}
 
-	if (newaction) {
-		if (sc->sc_mbuf_net == NULL) {
-			if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction,
-			    (void *)&sc->sc_statep_net.s)) == NULL) {
-				splx(s);
-				return (ENOMEM);
-			}
-		}
-		h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *);
-
-		switch (newaction) {
-		case PFSYNC_ACT_UPD_C:
-			if (i != 255) {
-				up = (void *)((char *)h_net +
-				    PFSYNC_HDRLEN + (i * sizeof(*up)));
-				up->updates++;
-			} else {
-				h_net->count++;
-				sc->sc_mbuf_net->m_pkthdr.len =
-				    sc->sc_mbuf_net->m_len += sizeof(*up);
-				up = sc->sc_statep_net.u++;
-
-				bzero(up, sizeof(*up));
-				bcopy(&st->id, up->id, sizeof(up->id));
-				up->creatorid = st->creatorid;
-			}
-			up->timeout = st->timeout;
-			up->expire = sp->expire;
-			up->src = sp->src;
-			up->dst = sp->dst;
-			break;
-		case PFSYNC_ACT_DEL_C:
-			sc->sc_mbuf_net->m_pkthdr.len =
-			    sc->sc_mbuf_net->m_len += sizeof(*dp);
-			dp = sc->sc_statep_net.d++;
-			h_net->count++;
-
-			bzero(dp, sizeof(*dp));
-			bcopy(&st->id, dp->id, sizeof(dp->id));
-			dp->creatorid = st->creatorid;
-			break;
-		}
+		sc->sc_len += nlen;
+		TAILQ_INSERT_TAIL(&sc->sc_tdb_q, t, tdb_sync_entry);
+		SET(t->tdb_flags, TDBF_PFSYNC);
+		t->tdb_updates = 0;
+	} else {
+		if (++t->tdb_updates >= sc->sc_maxupdates)
+			schednetisr(NETISR_PFSYNC);
 	}
 
-	if (h->count == sc->sc_maxcount ||
-	    (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates)))
-		ret = pfsync_sendout(sc);
-
-	splx(s);
-	return (ret);
+	if (output)
+		SET(t->tdb_flags, TDBF_PFSYNC_RPL);
+	else
+		CLR(t->tdb_flags, TDBF_PFSYNC_RPL);
 }
 
-/* This must be called in splnet() */
-int
-pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
+void
+pfsync_delete_tdb(struct tdb *t)
 {
-	struct ifnet *ifp = NULL;
-	struct pfsync_header *h;
-	struct pfsync_softc *sc = pfsyncif;
-	struct pfsync_state_upd_req *rup;
-	int ret = 0;
-
-	if (sc == NULL)
-		return (0);
-
 #ifdef __FreeBSD__
-	ifp = sc->sc_ifp;
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-	ifp = &sc->sc_if;
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-	if (sc->sc_mbuf == NULL) {
-		if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
-		    (void *)&sc->sc_statep.s)) == NULL)
-			return (ENOMEM);
-		h = mtod(sc->sc_mbuf, struct pfsync_header *);
-	} else {
-		h = mtod(sc->sc_mbuf, struct pfsync_header *);
-		if (h->action != PFSYNC_ACT_UREQ) {
-			pfsync_sendout(sc);
-			if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
-			    (void *)&sc->sc_statep.s)) == NULL)
-				return (ENOMEM);
-			h = mtod(sc->sc_mbuf, struct pfsync_header *);
-		}
-	}
 
-	if (src != NULL)
-		sc->sc_sendaddr = *src;
-	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
-	h->count++;
-	rup = sc->sc_statep.r++;
-	bzero(rup, sizeof(*rup));
-	if (up != NULL) {
-		bcopy(up->id, rup->id, sizeof(rup->id));
-		rup->creatorid = up->creatorid;
-	}
+	if (sc == NULL || !ISSET(t->tdb_flags, TDBF_PFSYNC))
+		return;
 
-	if (h->count == sc->sc_maxcount)
-		ret = pfsync_sendout(sc);
+	sc->sc_len -= sizeof(struct pfsync_tdb);
+	TAILQ_REMOVE(&sc->sc_tdb_q, t, tdb_sync_entry);
+	CLR(t->tdb_flags, TDBF_PFSYNC);
 
-	return (ret);
+	if (TAILQ_EMPTY(&sc->sc_tdb_q))
+		sc->sc_len -= sizeof(struct pfsync_subheader);
 }
 
 int
-pfsync_clear_states(u_int32_t creatorid, char *ifname)
+pfsync_out_tdb(struct tdb *t, struct mbuf *m, int offset)
 {
-	struct ifnet *ifp = NULL;
-	struct pfsync_softc *sc = pfsyncif;
-	struct pfsync_state_clr *cp;
-	int s, ret;
-
-	if (sc == NULL)
-		return (0);
+	struct pfsync_tdb *ut = (struct pfsync_tdb *)(m->m_data + offset);
 
-#ifdef __FreeBSD__
-	ifp = sc->sc_ifp;
-#else
-	ifp = &sc->sc_if;
-#endif
-#ifdef __FreeBSD__
-	PF_ASSERT(MA_OWNED);
-#endif
-	s = splnet();
-	if (sc->sc_mbuf != NULL)
-		pfsync_sendout(sc);
-	if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR,
-	    (void *)&sc->sc_statep.c)) == NULL) {
-		splx(s);
-		return (ENOMEM);
-	}
-	sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp);
-	cp = sc->sc_statep.c;
-	cp->creatorid = creatorid;
-	if (ifname != NULL)
-		strlcpy(cp->ifname, ifname, IFNAMSIZ);
+	bzero(ut, sizeof(*ut));
+	ut->spi = t->tdb_spi;
+	bcopy(&t->tdb_dst, &ut->dst, sizeof(ut->dst));
+	/*
+	 * When a failover happens, the master's rpl is probably above
+	 * what we see here (we may be up to a second late), so
+	 * increase it a bit for outbound tdbs to manage most such
+	 * situations.
+	 *
+	 * For now, just add an offset that is likely to be larger
+	 * than the number of packets we can see in one second. The RFC
+	 * just says the next packet must have a higher seq value.
+	 *
+	 * XXX What is a good algorithm for this? We could use
+	 * a rate-determined increase, but to know it, we would have
+	 * to extend struct tdb.
+	 * XXX pt->rpl can wrap over MAXINT, but if so the real tdb
+	 * will soon be replaced anyway. For now, just don't handle
+	 * this edge case.
+	 */
+#define RPL_INCR 16384
+	ut->rpl = htonl(t->tdb_rpl + (ISSET(t->tdb_flags, TDBF_PFSYNC_RPL) ?
+	    RPL_INCR : 0));
+	ut->cur_bytes = htobe64(t->tdb_cur_bytes);
+	ut->sproto = t->tdb_sproto;
 
-	ret = (pfsync_sendout(sc));
-	splx(s);
-	return (ret);
+	return (sizeof(*ut));
 }
+#endif
 
 void
-pfsync_timeout(void *v)
+pfsync_bulk_start(void)
 {
-	struct pfsync_softc *sc = v;
-	int s;
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = V_pfsyncif;
+#else
+	struct pfsync_softc *sc = pfsyncif;
+#endif
 
-	s = splnet();
+	sc->sc_ureq_received = time_uptime;
+
+	if (sc->sc_bulk_next == NULL)
 #ifdef __FreeBSD__
-	PF_LOCK();
+		sc->sc_bulk_next = TAILQ_FIRST(&V_state_list);
+#else
+		sc->sc_bulk_next = TAILQ_FIRST(&state_list);
 #endif
-	pfsync_sendout(sc);
+	sc->sc_bulk_last = sc->sc_bulk_next;
+
 #ifdef __FreeBSD__
-	PF_UNLOCK();
+	if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
+	if (pf_status.debug >= PF_DEBUG_MISC)
 #endif
-	splx(s);
+		printf("pfsync: received bulk update request\n");
+
+	pfsync_bulk_status(PFSYNC_BUS_START);
+	pfsync_bulk_update(sc);
 }
 
-#ifdef PFSYNC_TDB
 void
-pfsync_tdb_timeout(void *v)
+pfsync_bulk_update(void *arg)
 {
-	struct pfsync_softc *sc = v;
+	struct pfsync_softc *sc = arg;
+	struct pf_state *st = sc->sc_bulk_next;
+	int i = 0;
 	int s;
 
-	s = splnet();
+	s = splsoftnet();
 #ifdef __FreeBSD__
+	CURVNET_SET(sc->sc_ifp->if_vnet);
 	PF_LOCK();
 #endif
-	pfsync_tdb_sendout(sc);
+	do {
+		if (st->sync_state == PFSYNC_S_NONE &&
+		    st->timeout < PFTM_MAX &&
+		    st->pfsync_time <= sc->sc_ureq_received) {
+			pfsync_update_state_req(st);
+			i++;
+		}
+
+		st = TAILQ_NEXT(st, entry_list);
+		if (st == NULL)
 #ifdef __FreeBSD__
-	PF_UNLOCK();
+			st = TAILQ_FIRST(&V_state_list);
+#else
+			st = TAILQ_FIRST(&state_list);
 #endif
-	splx(s);
-}
+
+		if (i > 0 && TAILQ_EMPTY(&sc->sc_qs[PFSYNC_S_UPD])) {
+			sc->sc_bulk_next = st;
+#ifdef __FreeBSD__
+			callout_reset(&sc->sc_bulk_tmo, 1,
+			    pfsync_bulk_fail, sc);
+#else
+			timeout_add(&sc->sc_bulk_tmo, 1);
 #endif
+			goto out;
+		}
+	} while (st != sc->sc_bulk_last);
 
-/* This must be called in splnet() */
-void
-pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
-{
-	struct pfsync_state_bus *bus;
+	/* we're done */
+	sc->sc_bulk_next = NULL;
+	sc->sc_bulk_last = NULL;
+	pfsync_bulk_status(PFSYNC_BUS_END);
 
+out:
 #ifdef __FreeBSD__
-	PF_ASSERT(MA_OWNED);
+	PF_UNLOCK();
+	CURVNET_RESTORE();
 #endif
-	if (sc->sc_mbuf != NULL)
-		pfsync_sendout(sc);
-
-	if (pfsync_sync_ok &&
-	    (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
-	    (void *)&sc->sc_statep.b)) != NULL) {
-		sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
-		bus = sc->sc_statep.b;
-		bus->creatorid = pf_status.hostid;
-		bus->status = status;
-		bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
-		pfsync_sendout(sc);
-	}
+	splx(s);
 }
 
 void
-pfsync_bulk_update(void *v)
+pfsync_bulk_status(u_int8_t status)
 {
-	struct pfsync_softc *sc = v;
-	int s, i = 0;
-	struct pf_state *state;
-
-	s = splnet();
-#ifdef __FreeBSD__
-	PF_LOCK();
-#endif
-	if (sc->sc_mbuf != NULL)
-		pfsync_sendout(sc);
-
-	/*
-	 * Grab at most PFSYNC_BULKPACKETS worth of states which have not
-	 * been sent since the latest request was made.
-	 */
-	state = sc->sc_bulk_send_next;
-	if (state)
-		do {
-			/* send state update if syncable and not already sent */
-			if (!state->sync_flags
-			    && state->timeout < PFTM_MAX
-			    && state->pfsync_time <= sc->sc_ureq_received) {
-				pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
-				i++;
-			}
-
-			/* figure next state to send */
-			state = TAILQ_NEXT(state, u.s.entry_list);
-
-			/* wrap to start of list if we hit the end */
-			if (!state)
-				state = TAILQ_FIRST(&state_list);
-		} while (i < sc->sc_maxcount * PFSYNC_BULKPACKETS &&
-		    state != sc->sc_bulk_terminator);
-
-	if (!state || state == sc->sc_bulk_terminator) {
-		/* we're done */
-		pfsync_send_bus(sc, PFSYNC_BUS_END);
-		sc->sc_ureq_received = 0;
-		sc->sc_bulk_send_next = NULL;
-		sc->sc_bulk_terminator = NULL;
-		timeout_del(&sc->sc_bulk_tmo);
-		if (pf_status.debug >= PF_DEBUG_MISC)
-			printf("pfsync: bulk update complete\n");
-	} else {
-		/* look again for more in a bit */
+	struct {
+		struct pfsync_subheader subh;
+		struct pfsync_bus bus;
+	} __packed r;
+
 #ifdef __FreeBSD__
-		callout_reset(&sc->sc_bulk_tmo, 1, pfsync_bulk_update,
-		    pfsyncif);
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-		timeout_add(&sc->sc_bulk_tmo, 1);
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-		sc->sc_bulk_send_next = state;
-	}
-	if (sc->sc_mbuf != NULL)
-		pfsync_sendout(sc);
-	splx(s);
+
+	bzero(&r, sizeof(r));
+
+	r.subh.action = PFSYNC_ACT_BUS;
+	r.subh.count = htons(1);
+
 #ifdef __FreeBSD__
-	PF_UNLOCK();
+	r.bus.creatorid = V_pf_status.hostid;
+#else
+	r.bus.creatorid = pf_status.hostid;
 #endif
+	r.bus.endtime = htonl(time_uptime - sc->sc_ureq_received);
+	r.bus.status = status;
+
+	pfsync_send_plus(&r, sizeof(r));
 }
 
 void
-pfsync_bulkfail(void *v)
+pfsync_bulk_fail(void *arg)
 {
-	struct pfsync_softc *sc = v;
-	int s, error;
+	struct pfsync_softc *sc = arg;
 
 #ifdef __FreeBSD__
-	PF_LOCK();
+	CURVNET_SET(sc->sc_ifp->if_vnet);
 #endif
+
 	if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
-		/* Try again in a bit */
+		/* Try again */
 #ifdef __FreeBSD__
-		callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail,
-		    pfsyncif);
+		callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
+		    pfsync_bulk_fail, V_pfsyncif);
 #else
-		timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
+		timeout_add_sec(&sc->sc_bulkfail_tmo, 5);
 #endif
-		s = splnet();
-		error = pfsync_request_update(NULL, NULL);
-		if (error == ENOMEM) {
-			if (pf_status.debug >= PF_DEBUG_MISC)
-				printf("pfsync: cannot allocate mbufs for "
-				    "bulk update\n");
-		} else
-			pfsync_sendout(sc);
-		splx(s);
+		pfsync_request_update(0, 0);
 	} else {
 		/* Pretend like the transfer was ok */
 		sc->sc_ureq_sent = 0;
 		sc->sc_bulk_tries = 0;
 #if NCARP > 0
-		if (!pfsync_sync_ok)
+#ifdef notyet
 #ifdef __FreeBSD__
-#ifdef CARP_ADVANCED
-			carp_group_demote_adj(sc->sc_ifp, -1);
-#endif
+		if (!sc->pfsync_sync_ok)
 #else
+		if (!pfsync_sync_ok)
+#endif
 			carp_group_demote_adj(&sc->sc_if, -1);
 #endif
 #endif
-		pfsync_sync_ok = 1;
-		if (pf_status.debug >= PF_DEBUG_MISC)
-			printf("pfsync: failed to receive "
-			    "bulk update status\n");
-		timeout_del(&sc->sc_bulkfail_tmo);
-	}
 #ifdef __FreeBSD__
-	PF_UNLOCK();
+		sc->pfsync_sync_ok = 1;
+#else
+		pfsync_sync_ok = 1;
 #endif
-}
-
-/* This must be called in splnet() */
-int
-pfsync_sendout(struct pfsync_softc *sc)
-{
-#if NBPFILTER > 0
 #ifdef __FreeBSD__
-	struct ifnet *ifp = sc->sc_ifp;
+		if (V_pf_status.debug >= PF_DEBUG_MISC)
 #else
-	struct ifnet *ifp = &sc->sc_if;
-#endif
+		if (pf_status.debug >= PF_DEBUG_MISC)
 #endif
-	struct mbuf *m;
+			printf("pfsync: failed to receive bulk update\n");
+	}
 
 #ifdef __FreeBSD__
-	PF_ASSERT(MA_OWNED);
+	CURVNET_RESTORE();
 #endif
-	timeout_del(&sc->sc_tmo);
-
-	if (sc->sc_mbuf == NULL)
-		return (0);
-	m = sc->sc_mbuf;
-	sc->sc_mbuf = NULL;
-	sc->sc_statep.s = NULL;
+}
 
-#if NBPFILTER > 0
-	if (ifp->if_bpf)
+void
+pfsync_send_plus(void *plus, size_t pluslen)
+{
 #ifdef __FreeBSD__
-		BPF_MTAP(ifp, m);
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
-#endif
+	struct pfsync_softc *sc = pfsyncif;
 #endif
+	int s;
 
-	if (sc->sc_mbuf_net) {
-		m_freem(m);
-		m = sc->sc_mbuf_net;
-		sc->sc_mbuf_net = NULL;
-		sc->sc_statep_net.s = NULL;
-	}
-
-	return pfsync_sendout_mbuf(sc, m);
-}
-
-#ifdef PFSYNC_TDB
-int
-pfsync_tdb_sendout(struct pfsync_softc *sc)
-{
-#if NBPFILTER > 0
 #ifdef __FreeBSD__
-	struct ifnet *ifp = sc->sc_ifp;
+	if (sc->sc_len + pluslen > sc->sc_ifp->if_mtu) {
 #else
-	struct ifnet *ifp = &sc->sc_if;
+	if (sc->sc_len + pluslen > sc->sc_if.if_mtu) {
 #endif
+		s = splnet();
+#ifdef __FreeBSD__
+		PF_LOCK();
 #endif
-	struct mbuf *m;
-
+		pfsync_sendout();
 #ifdef __FreeBSD__
-	PF_ASSERT(MA_OWNED);
+		PF_UNLOCK();
 #endif
-	timeout_del(&sc->sc_tdb_tmo);
+		splx(s);
+	}
 
-	if (sc->sc_mbuf_tdb == NULL)
-		return (0);
-	m = sc->sc_mbuf_tdb;
-	sc->sc_mbuf_tdb = NULL;
-	sc->sc_statep_tdb.t = NULL;
+	sc->sc_plus = plus;
+	sc->sc_len += (sc->sc_pluslen = pluslen);
 
-#if NBPFILTER > 0
-	if (ifp->if_bpf)
+	s = splnet();
 #ifdef __FreeBSD__
-		BPF_MTAP(ifp, m);
-#else
-		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+	PF_LOCK();
 #endif
+	pfsync_sendout();
+#ifdef __FreeBSD__
+	PF_UNLOCK();
 #endif
-
-	return pfsync_sendout_mbuf(sc, m);
+	splx(s);
 }
-#endif
 
 int
-pfsync_sendout_mbuf(struct pfsync_softc *sc, struct mbuf *m)
+pfsync_up(void)
 {
-	struct sockaddr sa;
-	struct ip *ip;
-
-#ifdef __FreeBSD__
-	PF_ASSERT(MA_OWNED);
-#endif
-	if (sc->sc_sync_ifp ||
-#ifdef __FreeBSD__
-	    sc->sc_sync_peer.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
-#else
-	    sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
-#endif
-		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
-		if (m == NULL) {
-			pfsyncstats.pfsyncs_onomem++;
-			return (0);
-		}
-		ip = mtod(m, struct ip *);
-		ip->ip_v = IPVERSION;
-		ip->ip_hl = sizeof(*ip) >> 2;
-		ip->ip_tos = IPTOS_LOWDELAY;
 #ifdef __FreeBSD__
-		ip->ip_len = m->m_pkthdr.len;
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-		ip->ip_len = htons(m->m_pkthdr.len);
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-		ip->ip_id = htons(ip_randomid());
+
 #ifdef __FreeBSD__
-		ip->ip_off = IP_DF;
+	if (sc == NULL || !ISSET(sc->sc_ifp->if_flags, IFF_DRV_RUNNING))
 #else
-		ip->ip_off = htons(IP_DF);
+	if (sc == NULL || !ISSET(sc->sc_if.if_flags, IFF_RUNNING))
 #endif
-		ip->ip_ttl = PFSYNC_DFLTTL;
-		ip->ip_p = IPPROTO_PFSYNC;
-		ip->ip_sum = 0;
+		return (0);
 
-		bzero(&sa, sizeof(sa));
-		ip->ip_src.s_addr = INADDR_ANY;
+	return (1);
+}
 
+int
+pfsync_state_in_use(struct pf_state *st)
+{
 #ifdef __FreeBSD__
-		if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP))
+	struct pfsync_softc *sc = V_pfsyncif;
 #else
-		if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
+	struct pfsync_softc *sc = pfsyncif;
 #endif
-			m->m_flags |= M_MCAST;
-		ip->ip_dst = sc->sc_sendaddr;
-		sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
 
-		pfsyncstats.pfsyncs_opackets++;
+	if (sc == NULL)
+		return (0);
 
-#ifdef __FreeBSD__
-		if (!IF_HANDOFF(&sc->sc_ifq, m, NULL))
-			pfsyncstats.pfsyncs_oerrors++;
-		taskqueue_enqueue(taskqueue_thread, &pfsyncif->sc_send_task);
-#else
-		if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
-			pfsyncstats.pfsyncs_oerrors++;
-#endif
-	} else
-		m_freem(m);
+	if (st->sync_state != PFSYNC_S_NONE)
+		return (1);
 
-	return (0);
+	if (sc->sc_bulk_next == NULL && sc->sc_bulk_last == NULL)
+		return (0);
+
+	return (1);
 }
 
-#ifdef PFSYNC_TDB
-/* Update an in-kernel tdb. Silently fail if no tdb is found. */
+u_int pfsync_ints;
+u_int pfsync_tmos;
+
 void
-pfsync_update_net_tdb(struct pfsync_tdb *pt)
+pfsync_timeout(void *arg)
 {
-	struct tdb		*tdb;
-	int			 s;
-
-	/* check for invalid values */
-	if (ntohl(pt->spi) <= SPI_RESERVED_MAX ||
-	    (pt->dst.sa.sa_family != AF_INET &&
-	     pt->dst.sa.sa_family != AF_INET6))
-		goto bad;
+#if defined(__FreeBSD__) && defined(VIMAGE)
+	struct pfsync_softc *sc = arg;
+#endif
+	int s;
 
-	s = spltdb();
-	tdb = gettdb(pt->spi, &pt->dst, pt->sproto);
-	if (tdb) {
-		pt->rpl = ntohl(pt->rpl);
-		pt->cur_bytes = betoh64(pt->cur_bytes);
+#ifdef __FreeBSD__
+	CURVNET_SET(sc->sc_ifp->if_vnet);
+#endif
 
-		/* Neither replay nor byte counter should ever decrease. */
-		if (pt->rpl < tdb->tdb_rpl ||
-		    pt->cur_bytes < tdb->tdb_cur_bytes) {
-			splx(s);
-			goto bad;
-		}
+	pfsync_tmos++;
 
-		tdb->tdb_rpl = pt->rpl;
-		tdb->tdb_cur_bytes = pt->cur_bytes;
-	}
+	s = splnet();
+#ifdef __FreeBSD__
+	PF_LOCK();
+#endif
+	pfsync_sendout();
+#ifdef __FreeBSD__
+	PF_UNLOCK();
+#endif
 	splx(s);
-	return;
 
- bad:
-	if (pf_status.debug >= PF_DEBUG_MISC)
-		printf("pfsync_insert: PFSYNC_ACT_TDB_UPD: "
-		    "invalid value\n");
-	pfsyncstats.pfsyncs_badstate++;
-	return;
+#ifdef __FreeBSD__
+	CURVNET_RESTORE();
+#endif
 }
 
-/* One of our local tdbs have been updated, need to sync rpl with others */
-int
-pfsync_update_tdb(struct tdb *tdb, int output)
+/* this is a softnet/netisr handler */
+void
+#ifdef __FreeBSD__
+pfsyncintr(void *arg)
+#else
+pfsyncintr(void)
+#endif
 {
-	struct ifnet *ifp = NULL;
-	struct pfsync_softc *sc = pfsyncif;
-	struct pfsync_header *h;
-	struct pfsync_tdb *pt = NULL;
-	int s, i, ret;
+#ifdef __FreeBSD__
+	struct pfsync_softc *sc = arg;
+#endif
+	int s;
 
+#ifdef __FreeBSD__
 	if (sc == NULL)
-		return (0);
+		return;
 
+	CURVNET_SET(sc->sc_ifp->if_vnet);
+#endif
+	pfsync_ints++;
+
+	s = splnet();
 #ifdef __FreeBSD__
-	ifp = sc->sc_ifp;
-#else
-	ifp = &sc->sc_if;
+	PF_LOCK();
 #endif
-	if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
+	pfsync_sendout();
 #ifdef __FreeBSD__
-	    sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
-#else
-	    sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
+	PF_UNLOCK();
 #endif
-		/* Don't leave any stale pfsync packets hanging around. */
-		if (sc->sc_mbuf_tdb != NULL) {
-			m_freem(sc->sc_mbuf_tdb);
-			sc->sc_mbuf_tdb = NULL;
-			sc->sc_statep_tdb.t = NULL;
-		}
-		return (0);
-	}
+	splx(s);
 
 #ifdef __FreeBSD__
-	PF_ASSERT(MA_OWNED);
+	CURVNET_RESTORE();
 #endif
-	s = splnet();
-	if (sc->sc_mbuf_tdb == NULL) {
-		if ((sc->sc_mbuf_tdb = pfsync_get_mbuf(sc, PFSYNC_ACT_TDB_UPD,
-		    (void *)&sc->sc_statep_tdb.t)) == NULL) {
-			splx(s);
-			return (ENOMEM);
-		}
-		h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
-	} else {
-		h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
-		if (h->action != PFSYNC_ACT_TDB_UPD) {
-			/*
-			 * XXX will never happen as long as there's
-			 * only one "TDB action".
-			 */
-			pfsync_tdb_sendout(sc);
-			sc->sc_mbuf_tdb = pfsync_get_mbuf(sc,
-			    PFSYNC_ACT_TDB_UPD, (void *)&sc->sc_statep_tdb.t);
-			if (sc->sc_mbuf_tdb == NULL) {
-				splx(s);
-				return (ENOMEM);
-			}
-			h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
-		} else if (sc->sc_maxupdates) {
-			/*
-			 * If it's an update, look in the packet to see if
-			 * we already have an update for the state.
-			 */
-			struct pfsync_tdb *u =
-			    (void *)((char *)h + PFSYNC_HDRLEN);
-
-			for (i = 0; !pt && i < h->count; i++) {
-				if (tdb->tdb_spi == u->spi &&
-				    tdb->tdb_sproto == u->sproto &&
-			            !bcmp(&tdb->tdb_dst, &u->dst,
-				    SA_LEN(&u->dst.sa))) {
-					pt = u;
-					pt->updates++;
-				}
-				u++;
-			}
-		}
-	}
+}
 
-	if (pt == NULL) {
-		/* not a "duplicate" update */
-		pt = sc->sc_statep_tdb.t++;
-		sc->sc_mbuf_tdb->m_pkthdr.len =
-		    sc->sc_mbuf_tdb->m_len += sizeof(struct pfsync_tdb);
-		h->count++;
-		bzero(pt, sizeof(*pt));
+int
+pfsync_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
+    size_t newlen)
+{
 
-		pt->spi = tdb->tdb_spi;
-		memcpy(&pt->dst, &tdb->tdb_dst, sizeof pt->dst);
-		pt->sproto = tdb->tdb_sproto;
+#ifdef notyet
+	/* All sysctl names at this level are terminal. */
+	if (namelen != 1)
+		return (ENOTDIR);
+
+	switch (name[0]) {
+	case PFSYNCCTL_STATS:
+		if (newp != NULL)
+			return (EPERM);
+		return (sysctl_struct(oldp, oldlenp, newp, newlen,
+		    &V_pfsyncstats, sizeof(V_pfsyncstats)));
 	}
-
-	/*
-	 * When a failover happens, the master's rpl is probably above
-	 * what we see here (we may be up to a second late), so
-	 * increase it a bit for outbound tdbs to manage most such
-	 * situations.
-	 *
-	 * For now, just add an offset that is likely to be larger
-	 * than the number of packets we can see in one second. The RFC
-	 * just says the next packet must have a higher seq value.
-	 *
-	 * XXX What is a good algorithm for this? We could use
-	 * a rate-determined increase, but to know it, we would have
-	 * to extend struct tdb.
-	 * XXX pt->rpl can wrap over MAXINT, but if so the real tdb
-	 * will soon be replaced anyway. For now, just don't handle
-	 * this edge case.
-	 */
-#define RPL_INCR 16384
-	pt->rpl = htonl(tdb->tdb_rpl + (output ? RPL_INCR : 0));
-	pt->cur_bytes = htobe64(tdb->tdb_cur_bytes);
-
-	if (h->count == sc->sc_maxcount ||
-	    (sc->sc_maxupdates && (pt->updates >= sc->sc_maxupdates)))
-		ret = pfsync_tdb_sendout(sc);
-
-	splx(s);
-	return (ret);
+#endif
+	return (ENOPROTOOPT);
 }
-#endif /* PFSYNC_TDB */
 
 #ifdef __FreeBSD__
 void
@@ -2243,18 +3305,15 @@ pfsync_ifdetach(void *arg, struct ifnet *ifp)
 	struct pfsync_softc *sc = (struct pfsync_softc *)arg;
 	struct ip_moptions *imo;
 
-	if (sc == NULL || sc->sc_sync_ifp != ifp)
+	if (sc == NULL || sc->sc_sync_if != ifp)
 		return;         /* not for us; unlocked read */
 
+	CURVNET_SET(sc->sc_ifp->if_vnet);
+
 	PF_LOCK();
 
 	/* Deal with a member interface going away from under us. */
-	sc->sc_sync_ifp = NULL;
-	if (sc->sc_mbuf_net != NULL) {
-		m_freem(sc->sc_mbuf_net);
-		sc->sc_mbuf_net = NULL;
-		sc->sc_statep_net.s = NULL;
-	}
+	sc->sc_sync_if = NULL;
 	imo = &sc->sc_imo;
 	if (imo->imo_num_memberships > 0) {
 		KASSERT(imo->imo_num_memberships == 1,
@@ -2272,29 +3331,73 @@ pfsync_ifdetach(void *arg, struct ifnet *ifp)
 	}
 
 	PF_UNLOCK();
+	
+	CURVNET_RESTORE();
 }
 
-void
-pfsync_senddef(void *arg, __unused int pending)
+static int
+vnet_pfsync_init(const void *unused)
 {
-	struct pfsync_softc *sc = (struct pfsync_softc *)arg;
-	struct mbuf *m;
+	int error = 0;
 
-	for(;;) {
-		IF_DEQUEUE(&sc->sc_ifq, m);
-		if (m == NULL)
-			break;
-		/* Deal with a member interface going away from under us. */
-		if (sc->sc_sync_ifp == NULL) {
-			pfsyncstats.pfsyncs_oerrors++;
-			m_freem(m);
-			continue;
-		}
-		if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
-			pfsyncstats.pfsyncs_oerrors++;
-	}
+	pfsyncattach(0);
+
+	error = swi_add(NULL, "pfsync", pfsyncintr, V_pfsyncif,
+		SWI_NET, INTR_MPSAFE, &pfsync_swi.pfsync_swi_cookie);
+	if (error)
+		panic("%s: swi_add %d", __func__, error);
+
+	pfsync_state_import_ptr = pfsync_state_import;
+	pfsync_up_ptr = pfsync_up;
+	pfsync_insert_state_ptr = pfsync_insert_state;
+	pfsync_update_state_ptr = pfsync_update_state;
+	pfsync_delete_state_ptr = pfsync_delete_state;
+	pfsync_clear_states_ptr = pfsync_clear_states;
+	pfsync_state_in_use_ptr = pfsync_state_in_use;
+	pfsync_defer_ptr = pfsync_defer;
+
+	return (0);
+}
+
+static int
+vnet_pfsync_uninit(const void *unused)
+{
+
+	swi_remove(pfsync_swi.pfsync_swi_cookie);
+
+	pfsync_state_import_ptr = NULL;
+	pfsync_up_ptr = NULL;
+	pfsync_insert_state_ptr = NULL;
+	pfsync_update_state_ptr = NULL;
+	pfsync_delete_state_ptr = NULL;
+	pfsync_clear_states_ptr = NULL;
+	pfsync_state_in_use_ptr = NULL;
+	pfsync_defer_ptr = NULL;
+
+	if_clone_detach(&pfsync_cloner);
+
+	return (0);
 }
 
+/* Define startup order. */
+#define	PFSYNC_SYSINIT_ORDER	SI_SUB_PROTO_BEGIN
+#define	PFSYNC_MODEVENT_ORDER	(SI_ORDER_FIRST) /* On boot slot in here. */
+#define	PFSYNC_VNET_ORDER	(PFSYNC_MODEVENT_ORDER + 2) /* Later still. */
+
+/*
+ * Starting up.
+ * VNET_SYSINIT is called for each existing vnet and each new vnet.
+ */
+VNET_SYSINIT(vnet_pfsync_init, PFSYNC_SYSINIT_ORDER, PFSYNC_VNET_ORDER,
+    vnet_pfsync_init, NULL);
+
+/*
+ * Closing up shop. These are done in REVERSE ORDER,
+ * Not called on reboot.
+ * VNET_SYSUNINIT is called for each exiting vnet as it exits.
+ */
+VNET_SYSUNINIT(vnet_pfsync_uninit, PFSYNC_SYSINIT_ORDER, PFSYNC_VNET_ORDER,
+    vnet_pfsync_uninit, NULL);
 static int
 pfsync_modevent(module_t mod, int type, void *data)
 {
@@ -2302,10 +3405,14 @@ pfsync_modevent(module_t mod, int type, void *data)
 
 	switch (type) {
 	case MOD_LOAD:
+#ifndef __FreeBSD__
 		pfsyncattach(0);
+#endif
 		break;
 	case MOD_UNLOAD:
+#ifndef __FreeBSD__
 		if_clone_detach(&pfsync_cloner);
+#endif
 		break;
 	default:
 		error = EINVAL;
@@ -2325,5 +3432,5 @@ static moduledata_t pfsync_mod = {
 
 DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
 MODULE_VERSION(pfsync, PFSYNC_MODVER);
-MODULE_DEPEND(pflog, pf, PF_MODVER, PF_MODVER, PF_MODVER);
+MODULE_DEPEND(pfsync, pf, PF_MODVER, PF_MODVER, PF_MODVER);
 #endif /* __FreeBSD__ */
diff --git a/sys/contrib/pf/net/if_pfsync.h b/sys/contrib/pf/net/if_pfsync.h
index f306610..17259b7 100644
--- a/sys/contrib/pf/net/if_pfsync.h
+++ b/sys/contrib/pf/net/if_pfsync.h
@@ -1,5 +1,4 @@
-/*	$FreeBSD$	*/
-/*	$OpenBSD: if_pfsync.h,v 1.30 2006/10/31 14:49:01 henning Exp $	*/
+/*	$OpenBSD: if_pfsync.h,v 1.35 2008/06/29 08:42:15 mcbride Exp $	*/
 
 /*
  * Copyright (c) 2001 Michael Shalayeff
@@ -27,227 +26,217 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * Copyright (c) 2008 David Gwynne 
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
 #ifndef _NET_IF_PFSYNC_H_
-#define _NET_IF_PFSYNC_H_
+#define	_NET_IF_PFSYNC_H_
 
+#define	PFSYNC_VERSION		5
+#define	PFSYNC_DFLTTL		255
 
-#define PFSYNC_ID_LEN	sizeof(u_int64_t)
+#define	PFSYNC_ACT_CLR		0	/* clear all states */
+#define	PFSYNC_ACT_INS		1	/* insert state */
+#define	PFSYNC_ACT_INS_ACK	2	/* ack of insterted state */
+#define	PFSYNC_ACT_UPD		3	/* update state */
+#define	PFSYNC_ACT_UPD_C	4	/* "compressed" update state */
+#define	PFSYNC_ACT_UPD_REQ	5	/* request "uncompressed" state */
+#define	PFSYNC_ACT_DEL		6	/* delete state */
+#define	PFSYNC_ACT_DEL_C	7	/* "compressed" delete state */
+#define	PFSYNC_ACT_INS_F	8	/* insert fragment */
+#define	PFSYNC_ACT_DEL_F	9	/* delete fragments */
+#define	PFSYNC_ACT_BUS		10	/* bulk update status */
+#define	PFSYNC_ACT_TDB		11	/* TDB replay counter update */
+#define	PFSYNC_ACT_EOF		12	/* end of frame */
+#define	PFSYNC_ACT_MAX		13
+
+#define	PFSYNC_ACTIONS		"CLR ST",		\
+				"INS ST",		\
+				"INS ST ACK",		\
+				"UPD ST",		\
+				"UPD ST COMP",		\
+				"UPD ST REQ",		\
+				"DEL ST",		\
+				"DEL ST COMP",		\
+				"INS FR",		\
+				"DEL FR",		\
+				"BULK UPD STAT",	\
+				"TDB UPD",		\
+				"EOF"
+
+#define	PFSYNC_HMAC_LEN	20
 
-struct pfsync_state_scrub {
-	u_int16_t	pfss_flags;
-	u_int8_t	pfss_ttl;	/* stashed TTL		*/
-#define PFSYNC_SCRUB_FLAG_VALID 	0x01
-	u_int8_t	scrub_flag;
-	u_int32_t	pfss_ts_mod;	/* timestamp modulation	*/
-} __packed;
+/*
+ * A pfsync frame is built from a header followed by several sections which
+ * are all prefixed with their own subheaders. Frames must be terminated with
+ * an EOF subheader.
+ *
+ * | ...			|
+ * | IP header			|
+ * +============================+
+ * | pfsync_header		|
+ * +----------------------------+
+ * | pfsync_subheader		|
+ * +----------------------------+
+ * | first action fields	|
+ * | ...			|
+ * +----------------------------+
+ * | pfsync_subheader		|
+ * +----------------------------+
+ * | second action fields	|
+ * | ...			|
+ * +----------------------------+
+ * | EOF pfsync_subheader	|
+ * +----------------------------+
+ * | HMAC			|
+ * +============================+
+ */
 
-struct pfsync_state_host {
-	struct pf_addr	addr;
-	u_int16_t	port;
-	u_int16_t	pad[3];
+/*
+ * Frame header
+ */
+
+struct pfsync_header {
+	u_int8_t			version;
+	u_int8_t			_pad;
+	u_int16_t			len;
+	u_int8_t			pfcksum[PF_MD5_DIGEST_LENGTH];
 } __packed;
 
-struct pfsync_state_peer {
-	struct pfsync_state_scrub scrub;	/* state is scrubbed	*/
-	u_int32_t	seqlo;		/* Max sequence number sent	*/
-	u_int32_t	seqhi;		/* Max the other end ACKd + win	*/
-	u_int32_t	seqdiff;	/* Sequence number modulator	*/
-	u_int16_t	max_win;	/* largest window (pre scaling)	*/
-	u_int16_t	mss;		/* Maximum segment size option	*/
-	u_int8_t	state;		/* active state level		*/
-	u_int8_t	wscale;		/* window scaling factor	*/
-	u_int8_t	pad[6];
+/*
+ * Frame region subheader
+ */
+
+struct pfsync_subheader {
+	u_int8_t			action;
+	u_int8_t			_pad;
+	u_int16_t			count;
 } __packed;
 
-struct pfsync_state {
-	u_int32_t	 id[2];
-	char		 ifname[IFNAMSIZ];
-	struct pfsync_state_host lan;
-	struct pfsync_state_host gwy;
-	struct pfsync_state_host ext;
-	struct pfsync_state_peer src;
-	struct pfsync_state_peer dst;
-	struct pf_addr	 rt_addr;
-	u_int32_t	 rule;
-	u_int32_t	 anchor;
-	u_int32_t	 nat_rule;
-	u_int32_t	 creation;
-	u_int32_t	 expire;
-	u_int32_t	 packets[2][2];
-	u_int32_t	 bytes[2][2];
-	u_int32_t	 creatorid;
-	sa_family_t	 af;
-	u_int8_t	 proto;
-	u_int8_t	 direction;
-	u_int8_t	 log;
-	u_int8_t	 state_flags;
-	u_int8_t	 timeout;
-	u_int8_t	 sync_flags;
-	u_int8_t	 updates;
+/*
+ * CLR
+ */
+
+struct pfsync_clr {
+	char				ifname[IFNAMSIZ];
+	u_int32_t			creatorid;
 } __packed;
 
-#define PFSYNC_FLAG_COMPRESS 	0x01
-#define PFSYNC_FLAG_STALE	0x02
+/*
+ * INS, UPD, DEL
+ */
+
+/* these use struct pfsync_state in pfvar.h */
 
-#ifdef PFSYNC_TDB
-struct pfsync_tdb {
-	u_int32_t	spi;
-	union sockaddr_union dst;
-	u_int32_t	rpl;
-	u_int64_t	cur_bytes;
-	u_int8_t	sproto;
-	u_int8_t	updates;
-	u_int8_t	pad[2];
+/*
+ * INS_ACK
+ */
+
+struct pfsync_ins_ack {
+	u_int64_t			id;
+	u_int32_t			creatorid;
 } __packed;
-#endif
 
-struct pfsync_state_upd {
-	u_int32_t		id[2];
+/*
+ * UPD_C
+ */
+
+struct pfsync_upd_c {
+	u_int64_t			id;
 	struct pfsync_state_peer	src;
 	struct pfsync_state_peer	dst;
-	u_int32_t		creatorid;
-	u_int32_t		expire;
-	u_int8_t		timeout;
-	u_int8_t		updates;
-	u_int8_t		pad[6];
+	u_int32_t			creatorid;
+	u_int32_t			expire;
+	u_int8_t			timeout;
+	u_int8_t			_pad[3];
 } __packed;
 
-struct pfsync_state_del {
-	u_int32_t		id[2];
-	u_int32_t		creatorid;
-	struct {
-		u_int8_t	state;
-	} src;
-	struct {
-		u_int8_t	state;
-	} dst;
-	u_int8_t		pad[2];
-} __packed;
+/*
+ * UPD_REQ
+ */
 
-struct pfsync_state_upd_req {
-	u_int32_t		id[2];
-	u_int32_t		creatorid;
-	u_int32_t		pad;
+struct pfsync_upd_req {
+	u_int64_t			id;
+	u_int32_t			creatorid;
 } __packed;
 
-struct pfsync_state_clr {
-	char			ifname[IFNAMSIZ];
-	u_int32_t		creatorid;
-	u_int32_t		pad;
-} __packed;
+/*
+ * DEL_C
+ */
 
-struct pfsync_state_bus {
-	u_int32_t		creatorid;
-	u_int32_t		endtime;
-	u_int8_t		status;
-#define PFSYNC_BUS_START	1
-#define PFSYNC_BUS_END		2
-	u_int8_t		pad[7];
+struct pfsync_del_c {
+	u_int64_t			id;
+	u_int32_t			creatorid;
 } __packed;
 
-#ifdef _KERNEL
-
-union sc_statep {
-	struct pfsync_state	*s;
-	struct pfsync_state_upd	*u;
-	struct pfsync_state_del	*d;
-	struct pfsync_state_clr	*c;
-	struct pfsync_state_bus	*b;
-	struct pfsync_state_upd_req	*r;
-};
+/* 
+ * INS_F, DEL_F
+ */
 
-#ifdef PFSYNC_TDB
-union sc_tdb_statep {
-	struct pfsync_tdb	*t;
-};
-#endif
+/* not implemented (yet) */
 
-extern int	pfsync_sync_ok;
+/*
+ * BUS
+ */
 
-struct pfsync_softc {
-#ifdef __FreeBSD__
-	struct ifnet		*sc_ifp;
-#else
-	struct ifnet		 sc_if;
-#endif
-	struct ifnet		*sc_sync_ifp;
+struct pfsync_bus {
+	u_int32_t			creatorid;
+	u_int32_t			endtime;
+	u_int8_t			status;
+#define	PFSYNC_BUS_START			1
+#define	PFSYNC_BUS_END				2
+	u_int8_t			_pad[3];
+} __packed;
 
-	struct ip_moptions	 sc_imo;
-#ifdef __FreeBSD__
-	struct callout		 sc_tmo;
-#ifdef PFSYNC_TDB
-	struct callout		 sc_tdb_tmo;
-#endif
-	struct callout		 sc_bulk_tmo;
-	struct callout		 sc_bulkfail_tmo;
-#else
-	struct timeout		 sc_tmo;
-	struct timeout		 sc_tdb_tmo;
-	struct timeout		 sc_bulk_tmo;
-	struct timeout		 sc_bulkfail_tmo;
-#endif
-	struct in_addr		 sc_sync_peer;
-	struct in_addr		 sc_sendaddr;
-	struct mbuf		*sc_mbuf;	/* current cumulative mbuf */
-	struct mbuf		*sc_mbuf_net;	/* current cumulative mbuf */
-#ifdef PFSYNC_TDB
-    	struct mbuf		*sc_mbuf_tdb;	/* dito for TDB updates */
-#endif
-#ifdef __FreeBSD__
-	struct ifqueue		 sc_ifq;
-	struct task		 sc_send_task;
-#endif
-	union sc_statep		 sc_statep;
-	union sc_statep		 sc_statep_net;
-#ifdef PFSYNC_TDB
-	union sc_tdb_statep	 sc_statep_tdb;
-#endif
-	u_int32_t		 sc_ureq_received;
-	u_int32_t		 sc_ureq_sent;
-	struct pf_state		*sc_bulk_send_next;
-	struct pf_state		*sc_bulk_terminator;
-	int			 sc_bulk_tries;
-	int			 sc_maxcount;	/* number of states in mtu */
-	int			 sc_maxupdates;	/* number of updates/state */
-#ifdef __FreeBSD__
-	eventhandler_tag	 sc_detachtag;
-#endif
-};
+/*
+ * TDB
+ */
 
-extern struct pfsync_softc	*pfsyncif;
-#endif
+struct pfsync_tdb {
+	u_int32_t			spi;
+	union sockaddr_union		dst;
+	u_int32_t			rpl;
+	u_int64_t			cur_bytes;
+	u_int8_t			sproto;
+	u_int8_t			updates;
+	u_int8_t			_pad[2];
+} __packed;
 
+/*
+ * EOF
+ */
 
-struct pfsync_header {
-	u_int8_t version;
-#define	PFSYNC_VERSION	3
-	u_int8_t af;
-	u_int8_t action;
-#define	PFSYNC_ACT_CLR		0	/* clear all states */
-#define	PFSYNC_ACT_INS		1	/* insert state */
-#define	PFSYNC_ACT_UPD		2	/* update state */
-#define	PFSYNC_ACT_DEL		3	/* delete state */
-#define	PFSYNC_ACT_UPD_C	4	/* "compressed" state update */
-#define	PFSYNC_ACT_DEL_C	5	/* "compressed" state delete */
-#define	PFSYNC_ACT_INS_F	6	/* insert fragment */
-#define	PFSYNC_ACT_DEL_F	7	/* delete fragments */
-#define	PFSYNC_ACT_UREQ		8	/* request "uncompressed" state */
-#define PFSYNC_ACT_BUS		9	/* Bulk Update Status */
-#define PFSYNC_ACT_TDB_UPD	10	/* TDB replay counter update */
-#define	PFSYNC_ACT_MAX		11
-	u_int8_t count;
-	u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
+struct pfsync_eof {
+	u_int8_t			hmac[PFSYNC_HMAC_LEN];
 } __packed;
 
-#define PFSYNC_BULKPACKETS	1	/* # of packets per timeout */
-#define PFSYNC_MAX_BULKTRIES	12
-#define PFSYNC_HDRLEN	sizeof(struct pfsync_header)
-#define	PFSYNC_ACTIONS \
-	"CLR ST", "INS ST", "UPD ST", "DEL ST", \
-	"UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \
-	"UPD REQ", "BLK UPD STAT", "TDB UPD"
+#define	PFSYNC_HDRLEN		sizeof(struct pfsync_header)
+
 
-#define PFSYNC_DFLTTL		255
+
+/*
+ * Names for PFSYNC sysctl objects
+ */
+#define	PFSYNCCTL_STATS		1	/* PFSYNC stats */
+#define	PFSYNCCTL_MAXID		2
+
+#define	PFSYNCCTL_NAMES { \
+	{ 0, 0 }, \
+	{ "stats", CTLTYPE_STRUCT }, \
+}
 
 struct pfsyncstats {
 	u_int64_t	pfsyncs_ipackets;	/* total input packets, IPv4 */
@@ -280,96 +269,56 @@ struct pfsyncreq {
 };
 
 #ifdef __FreeBSD__
-#define	SIOCSETPFSYNC	_IOW('i', 247, struct ifreq)
-#define	SIOCGETPFSYNC	_IOWR('i', 248, struct ifreq)
+#define	SIOCSETPFSYNC   _IOW('i', 247, struct ifreq)
+#define	SIOCGETPFSYNC   _IOWR('i', 248, struct ifreq)
 #endif
 
-#define pf_state_peer_hton(s,d) do {		\
-	(d)->seqlo = htonl((s)->seqlo);		\
-	(d)->seqhi = htonl((s)->seqhi);		\
-	(d)->seqdiff = htonl((s)->seqdiff);	\
-	(d)->max_win = htons((s)->max_win);	\
-	(d)->mss = htons((s)->mss);		\
-	(d)->state = (s)->state;		\
-	(d)->wscale = (s)->wscale;		\
-	if ((s)->scrub) {						\
-		(d)->scrub.pfss_flags = 				\
-		    htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP);	\
-		(d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl;		\
-		(d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\
-		(d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID;	\
-	}								\
-} while (0)
-
-#define pf_state_peer_ntoh(s,d) do {		\
-	(d)->seqlo = ntohl((s)->seqlo);		\
-	(d)->seqhi = ntohl((s)->seqhi);		\
-	(d)->seqdiff = ntohl((s)->seqdiff);	\
-	(d)->max_win = ntohs((s)->max_win);	\
-	(d)->mss = ntohs((s)->mss);		\
-	(d)->state = (s)->state;		\
-	(d)->wscale = (s)->wscale;		\
-	if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && 	\
-	    (d)->scrub != NULL) {					\
-		(d)->scrub->pfss_flags =				\
-		    ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP;	\
-		(d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl;		\
-		(d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\
-	}								\
-} while (0)
-
-#define pf_state_host_hton(s,d) do {				\
-	bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr));	\
-	(d)->port = (s)->port;					\
-} while (0)
-
-#define pf_state_host_ntoh(s,d) do {				\
-	bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr));	\
-	(d)->port = (s)->port;					\
-} while (0)
-
-#define pf_state_counter_hton(s,d) do {				\
-	d[0] = htonl((s>>32)&0xffffffff);			\
-	d[1] = htonl(s&0xffffffff);				\
-} while (0)
-
-#define pf_state_counter_ntoh(s,d) do {				\
-	d = ntohl(s[0]);					\
-	d = d<<32;						\
-	d += ntohl(s[1]);					\
-} while (0)
-
 #ifdef _KERNEL
+
+/*
+ * this shows where a pf state is with respect to the syncing.
+ */
+#define	PFSYNC_S_INS	0x00
+#define	PFSYNC_S_IACK	0x01
+#define	PFSYNC_S_UPD	0x02
+#define	PFSYNC_S_UPD_C	0x03
+#define	PFSYNC_S_DEL	0x04
+#define	PFSYNC_S_COUNT	0x05
+
+#define	PFSYNC_S_DEFER	0xfe
+#define	PFSYNC_S_NONE	0xff
+
 #ifdef __FreeBSD__
-void pfsync_input(struct mbuf *, __unused int);
+void			pfsync_input(struct mbuf *, __unused int);
 #else
-void pfsync_input(struct mbuf *, ...);
+void			pfsync_input(struct mbuf *, ...);
 #endif
-int pfsync_clear_states(u_int32_t, char *);
-int pfsync_pack_state(u_int8_t, struct pf_state *, int);
-#define pfsync_insert_state(st)	do {				\
-	if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) ||	\
-	    (st->proto == IPPROTO_PFSYNC))			\
-		st->sync_flags |= PFSTATE_NOSYNC;		\
-	else if (!st->sync_flags)				\
-		pfsync_pack_state(PFSYNC_ACT_INS, (st), 	\
-		    PFSYNC_FLAG_COMPRESS);			\
-	st->sync_flags &= ~PFSTATE_FROMSYNC;			\
-} while (0)
-#define pfsync_update_state(st) do {				\
-	if (!st->sync_flags)					\
-		pfsync_pack_state(PFSYNC_ACT_UPD, (st), 	\
-		    PFSYNC_FLAG_COMPRESS);			\
-	st->sync_flags &= ~PFSTATE_FROMSYNC;			\
-} while (0)
-#define pfsync_delete_state(st) do {				\
-	if (!st->sync_flags)					\
-		pfsync_pack_state(PFSYNC_ACT_DEL, (st),		\
-		    PFSYNC_FLAG_COMPRESS);			\
-} while (0)
-#ifdef PFSYNC_TDB
-int pfsync_update_tdb(struct tdb *, int);
+int			pfsync_sysctl(int *, u_int,  void *, size_t *,
+			    void *, size_t);
+
+#define	PFSYNC_SI_IOCTL		0x01
+#define	PFSYNC_SI_CKSUM		0x02
+#define	PFSYNC_SI_ACK		0x04
+int			pfsync_state_import(struct pfsync_state *, u_int8_t);
+#ifndef __FreeBSD__
+void			pfsync_state_export(struct pfsync_state *,
+			    struct pf_state *);
 #endif
+
+void			pfsync_insert_state(struct pf_state *);
+void			pfsync_update_state(struct pf_state *);
+void			pfsync_delete_state(struct pf_state *);
+void			pfsync_clear_states(u_int32_t, const char *);
+
+#ifdef notyet
+void			pfsync_update_tdb(struct tdb *, int);
+void			pfsync_delete_tdb(struct tdb *);
+#endif
+
+int			pfsync_defer(struct pf_state *, struct mbuf *);
+
+int			pfsync_up(void);
+int			pfsync_state_in_use(struct pf_state *);
 #endif
 
 #endif /* _NET_IF_PFSYNC_H_ */
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 135d734..5efd651 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -1,9 +1,8 @@
-/*	$OpenBSD: pf.c,v 1.527 2007/02/22 15:23:23 pyr Exp $ */
-/* add:	$OpenBSD: pf.c,v 1.559 2007/09/18 18:45:59 markus Exp $ */
+/*	$OpenBSD: pf.c,v 1.634 2009/02/27 12:37:45 henning Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
- * Copyright (c) 2002,2003 Henning Brauer
+ * Copyright (c) 2002 - 2008 Henning Brauer
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -66,10 +65,17 @@ __FBSDID("$FreeBSD$");
 #define	NPFSYNC		0
 #endif
 
+#ifdef DEV_PFLOW
+#define	NPFLOW		DEV_PFLOW
+#else
+#define	NPFLOW		0
+#endif
+
 #else
 #include "bpfilter.h"
 #include "pflog.h"
 #include "pfsync.h"
+#include "pflow.h"
 #endif
 
 #include 
@@ -81,8 +87,10 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #ifdef __FreeBSD__
+#include 
 #include 
 #include 
+#define	betoh64		be64toh
 #else
 #include 
 #endif
@@ -95,11 +103,21 @@ __FBSDID("$FreeBSD$");
 #include 
 #endif
 
+#ifdef __FreeBSD__
+#include 
+#else
+#include 
+#endif
+
 #include 
 #include 
 #include 
 #include 
-#ifndef __FreeBSD__
+#ifdef __FreeBSD__
+#ifdef RADIX_MPATH
+#include 
+#endif
+#else
 #include 
 #endif
 
@@ -118,16 +136,18 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
+#ifdef __FreeBSD__
+#include 
+#include  /* XXX: only for DIR_IN/DIR_OUT */
+#endif
 
 #ifndef __FreeBSD__
 #include 
 #endif
 #include 
 #include 
-
-#if NPFSYNC > 0
+#include 
 #include 
-#endif /* NPFSYNC > 0 */
 
 #ifdef INET6
 #include 
@@ -147,15 +167,61 @@ __FBSDID("$FreeBSD$");
 #include 
 
 extern int ip_optcopy(struct ip *, struct ip *);
-extern int debug_pfugidhack;
 #endif
 
-#define DPFPRINTF(n, x)	if (pf_status.debug >= (n)) printf x
+#ifdef __FreeBSD__
+#define	DPFPRINTF(n, x)	if (V_pf_status.debug >= (n)) printf x
+#else
+#define	DPFPRINTF(n, x)	if (pf_status.debug >= (n)) printf x
+#endif
 
 /*
  * Global variables
  */
 
+/* state tables */
+#ifdef __FreeBSD__
+VNET_DEFINE(struct pf_state_tree,	 pf_statetbl);
+
+VNET_DEFINE(struct pf_altqqueue,	 pf_altqs[2]);
+VNET_DEFINE(struct pf_palist,		 pf_pabuf);
+VNET_DEFINE(struct pf_altqqueue *,	 pf_altqs_active);
+VNET_DEFINE(struct pf_altqqueue *,	 pf_altqs_inactive);
+VNET_DEFINE(struct pf_status,		 pf_status);
+
+VNET_DEFINE(u_int32_t,			 ticket_altqs_active);
+VNET_DEFINE(u_int32_t,			 ticket_altqs_inactive);
+VNET_DEFINE(int,			 altqs_inactive_open);
+VNET_DEFINE(u_int32_t,			 ticket_pabuf);
+
+VNET_DEFINE(MD5_CTX,			 pf_tcp_secret_ctx);
+#define	V_pf_tcp_secret_ctx		 VNET(pf_tcp_secret_ctx)
+VNET_DEFINE(u_char,			 pf_tcp_secret[16]);
+#define	V_pf_tcp_secret			 VNET(pf_tcp_secret)
+VNET_DEFINE(int,			 pf_tcp_secret_init);
+#define	V_pf_tcp_secret_init		 VNET(pf_tcp_secret_init)
+VNET_DEFINE(int,			 pf_tcp_iss_off);
+#define	V_pf_tcp_iss_off		 VNET(pf_tcp_iss_off)
+
+struct pf_anchor_stackframe {
+	struct pf_ruleset		*rs;
+	struct pf_rule			*r;
+	struct pf_anchor_node		*parent;
+	struct pf_anchor		*child;
+};
+VNET_DEFINE(struct pf_anchor_stackframe, pf_anchor_stack[64]);
+#define	V_pf_anchor_stack		 VNET(pf_anchor_stack)
+
+VNET_DEFINE(uma_zone_t,	 pf_src_tree_pl);
+VNET_DEFINE(uma_zone_t,	 pf_rule_pl);
+VNET_DEFINE(uma_zone_t,	 pf_pooladdr_pl);
+VNET_DEFINE(uma_zone_t,	 pf_state_pl);
+VNET_DEFINE(uma_zone_t,	 pf_state_key_pl);
+VNET_DEFINE(uma_zone_t,	 pf_state_item_pl);
+VNET_DEFINE(uma_zone_t,	 pf_altq_pl);
+#else
+struct pf_state_tree	 pf_statetbl;
+
 struct pf_altqqueue	 pf_altqs[2];
 struct pf_palist	 pf_pabuf;
 struct pf_altqqueue	*pf_altqs_active;
@@ -167,6 +233,11 @@ u_int32_t		 ticket_altqs_inactive;
 int			 altqs_inactive_open;
 u_int32_t		 ticket_pabuf;
 
+MD5_CTX			 pf_tcp_secret_ctx;
+u_char			 pf_tcp_secret[16];
+int			 pf_tcp_secret_init;
+int			 pf_tcp_iss_off;
+
 struct pf_anchor_stackframe {
 	struct pf_ruleset			*rs;
 	struct pf_rule				*r;
@@ -174,16 +245,11 @@ struct pf_anchor_stackframe {
 	struct pf_anchor			*child;
 } pf_anchor_stack[64];
 
-#ifdef __FreeBSD__
-uma_zone_t		 pf_src_tree_pl, pf_rule_pl;
-uma_zone_t		 pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
-#else
-struct pool		 pf_src_tree_pl, pf_rule_pl;
-struct pool		 pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+struct pool		 pf_src_tree_pl, pf_rule_pl, pf_pooladdr_pl;
+struct pool		 pf_state_pl, pf_state_key_pl, pf_state_item_pl;
+struct pool		 pf_altq_pl;
 #endif
 
-void			 pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
-
 void			 pf_init_threshold(struct pf_threshold *, u_int32_t,
 			    u_int32_t);
 void			 pf_add_threshold(struct pf_threshold *);
@@ -212,18 +278,12 @@ void			 pf_send_tcp(const struct pf_rule *, sa_family_t,
 			    u_int16_t, u_int16_t, u_int32_t, u_int32_t,
 			    u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
 			    u_int16_t, struct ether_header *, struct ifnet *);
-void			 pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
+static void		 pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
 			    sa_family_t, struct pf_rule *);
-struct pf_rule		*pf_match_translation(struct pf_pdesc *, struct mbuf *,
-			    int, int, struct pfi_kif *,
-			    struct pf_addr *, u_int16_t, struct pf_addr *,
-			    u_int16_t, int);
-struct pf_rule		*pf_get_translation(struct pf_pdesc *, struct mbuf *,
-			    int, int, struct pfi_kif *, struct pf_src_node **,
-			    struct pf_addr *, u_int16_t,
-			    struct pf_addr *, u_int16_t,
-			    struct pf_addr *, u_int16_t *);
-int			 pf_test_tcp(struct pf_rule **, struct pf_state **,
+void			 pf_detach_state(struct pf_state *);
+void			 pf_state_key_detach(struct pf_state *, int);
+u_int32_t		 pf_tcp_iss(struct pf_pdesc *);
+int			 pf_test_rule(struct pf_rule **, struct pf_state **,
 			    int, struct pfi_kif *, struct mbuf *, int,
 			    void *, struct pf_pdesc *, struct pf_rule **,
 #ifdef __FreeBSD__
@@ -232,23 +292,14 @@ int			 pf_test_tcp(struct pf_rule **, struct pf_state **,
 #else
 			    struct pf_ruleset **, struct ifqueue *);
 #endif
-int			 pf_test_udp(struct pf_rule **, struct pf_state **,
-			    int, struct pfi_kif *, struct mbuf *, int,
-			    void *, struct pf_pdesc *, struct pf_rule **,
-#ifdef __FreeBSD__
-			    struct pf_ruleset **, struct ifqueue *,
-			    struct inpcb *);
-#else
-			    struct pf_ruleset **, struct ifqueue *);
-#endif
-int			 pf_test_icmp(struct pf_rule **, struct pf_state **,
-			    int, struct pfi_kif *, struct mbuf *, int,
-			    void *, struct pf_pdesc *, struct pf_rule **,
-			    struct pf_ruleset **, struct ifqueue *);
-int			 pf_test_other(struct pf_rule **, struct pf_state **,
-			    int, struct pfi_kif *, struct mbuf *, int, void *,
-			    struct pf_pdesc *, struct pf_rule **,
-			    struct pf_ruleset **, struct ifqueue *);
+static __inline int	 pf_create_state(struct pf_rule *, struct pf_rule *,
+			    struct pf_rule *, struct pf_pdesc *,
+			    struct pf_src_node *, struct pf_state_key *,
+			    struct pf_state_key *, struct pf_state_key *,
+			    struct pf_state_key *, struct mbuf *, int,
+			    u_int16_t, u_int16_t, int *, struct pfi_kif *,
+			    struct pf_state **, int, u_int16_t, u_int16_t,
+			    int);
 int			 pf_test_fragment(struct pf_rule **, int,
 			    struct pfi_kif *, struct mbuf *, void *,
 			    struct pf_pdesc *, struct pf_rule **,
@@ -257,7 +308,7 @@ int			 pf_tcp_track_full(struct pf_state_peer *,
 			    struct pf_state_peer *, struct pf_state **,
 			    struct pfi_kif *, struct mbuf *, int,
 			    struct pf_pdesc *, u_short *, int *);
-int			 pf_tcp_track_sloppy(struct pf_state_peer *,
+int			pf_tcp_track_sloppy(struct pf_state_peer *,
 			    struct pf_state_peer *, struct pf_state **,
 			    struct pf_pdesc *, u_short *);
 int			 pf_test_state_tcp(struct pf_state **, int,
@@ -270,30 +321,14 @@ int			 pf_test_state_icmp(struct pf_state **, int,
 			    struct pfi_kif *, struct mbuf *, int,
 			    void *, struct pf_pdesc *, u_short *);
 int			 pf_test_state_other(struct pf_state **, int,
-			    struct pfi_kif *, struct pf_pdesc *);
-int			 pf_match_tag(struct mbuf *, struct pf_rule *,
-			     struct pf_mtag *, int *);
-int			 pf_step_out_of_anchor(int *, struct pf_ruleset **,
-			     int, struct pf_rule **, struct pf_rule **,
-			     int *);
-void			 pf_hash(struct pf_addr *, struct pf_addr *,
-			    struct pf_poolhashkey *, sa_family_t);
-int			 pf_map_addr(u_int8_t, struct pf_rule *,
-			    struct pf_addr *, struct pf_addr *,
-			    struct pf_addr *, struct pf_src_node **);
-int			 pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
-			    struct pf_addr *, struct pf_addr *, u_int16_t,
-			    struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
-			    struct pf_src_node **);
+			    struct pfi_kif *, struct mbuf *, struct pf_pdesc *);
 void			 pf_route(struct mbuf **, struct pf_rule *, int,
 			    struct ifnet *, struct pf_state *,
 			    struct pf_pdesc *);
 void			 pf_route6(struct mbuf **, struct pf_rule *, int,
 			    struct ifnet *, struct pf_state *,
 			    struct pf_pdesc *);
-#ifdef __FreeBSD__
-/* XXX: import */
-#else
+#ifndef __FreeBSD__
 int			 pf_socket_lookup(int, struct pf_pdesc *);
 #endif
 u_int8_t		 pf_get_wscale(struct mbuf *, int, u_int16_t,
@@ -306,19 +341,32 @@ void			 pf_set_rt_ifp(struct pf_state *,
 			    struct pf_addr *);
 int			 pf_check_proto_cksum(struct mbuf *, int, int,
 			    u_int8_t, sa_family_t);
+#ifndef __FreeBSD__
+struct pf_divert	*pf_get_divert(struct mbuf *);
+#endif
+void			 pf_print_state_parts(struct pf_state *,
+			    struct pf_state_key *, struct pf_state_key *);
 int			 pf_addr_wrap_neq(struct pf_addr_wrap *,
 			    struct pf_addr_wrap *);
-struct pf_state		*pf_find_state_recurse(struct pfi_kif *,
-			    struct pf_state_cmp *, u_int8_t);
+int			 pf_compare_state_keys(struct pf_state_key *,
+			    struct pf_state_key *, struct pfi_kif *, u_int);
+#ifdef __FreeBSD__
+struct pf_state		*pf_find_state(struct pfi_kif *,
+			    struct pf_state_key_cmp *, u_int, struct mbuf *,
+			    struct pf_mtag *);
+#else
+struct pf_state		*pf_find_state(struct pfi_kif *,
+			    struct pf_state_key_cmp *, u_int, struct mbuf *);
+#endif
 int			 pf_src_connlimit(struct pf_state **);
 int			 pf_check_congestion(struct ifqueue *);
 
 #ifdef __FreeBSD__
 int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
 
-extern int pf_end_threads;
+VNET_DECLARE(int, pf_end_threads);
 
-struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
+VNET_DEFINE(struct pf_pool_limit, pf_pool_limits[PF_LIMIT_MAX]);
 #else
 extern struct pool pfr_ktable_pl;
 extern struct pool pfr_kentry_pl;
@@ -332,80 +380,101 @@ struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
 };
 #endif
 
-#define STATE_LOOKUP()							\
+#ifdef __FreeBSD__
+#define	PPACKET_LOOPED()						\
+	(pd->pf_mtag->flags & PF_PACKET_LOOPED)
+
+#define	PACKET_LOOPED()							\
+	(pd.pf_mtag->flags & PF_PACKET_LOOPED)
+
+#define	STATE_LOOKUP(i, k, d, s, m, pt)					\
 	do {								\
-		if (direction == PF_IN)					\
-			*state = pf_find_state_recurse(			\
-			    kif, &key, PF_EXT_GWY);			\
-		else							\
-			*state = pf_find_state_recurse(			\
-			    kif, &key, PF_LAN_EXT);			\
-		if (*state == NULL || (*state)->timeout == PFTM_PURGE)	\
+		s = pf_find_state(i, k, d, m, pt);			\
+		if (s == NULL || (s)->timeout == PFTM_PURGE)		\
 			return (PF_DROP);				\
-		if (direction == PF_OUT &&				\
-		    (((*state)->rule.ptr->rt == PF_ROUTETO &&		\
-		    (*state)->rule.ptr->direction == PF_OUT) ||		\
-		    ((*state)->rule.ptr->rt == PF_REPLYTO &&		\
-		    (*state)->rule.ptr->direction == PF_IN)) &&		\
-		    (*state)->rt_kif != NULL &&				\
-		    (*state)->rt_kif != kif)				\
+		if (PPACKET_LOOPED())					\
+			return (PF_PASS);				\
+		if (d == PF_OUT &&					\
+		    (((s)->rule.ptr->rt == PF_ROUTETO &&		\
+		    (s)->rule.ptr->direction == PF_OUT) ||		\
+		    ((s)->rule.ptr->rt == PF_REPLYTO &&			\
+		    (s)->rule.ptr->direction == PF_IN)) &&		\
+		    (s)->rt_kif != NULL &&				\
+		    (s)->rt_kif != i)					\
 			return (PF_PASS);				\
 	} while (0)
+#else
+#define	STATE_LOOKUP(i, k, d, s, m)					\
+	do {								\
+		s = pf_find_state(i, k, d, m);				\
+		if (s == NULL || (s)->timeout == PFTM_PURGE)		\
+			return (PF_DROP);				\
+		if (d == PF_OUT &&					\
+		    (((s)->rule.ptr->rt == PF_ROUTETO &&		\
+		    (s)->rule.ptr->direction == PF_OUT) ||		\
+		    ((s)->rule.ptr->rt == PF_REPLYTO &&			\
+		    (s)->rule.ptr->direction == PF_IN)) &&		\
+		    (s)->rt_kif != NULL &&				\
+		    (s)->rt_kif != i)					\
+			return (PF_PASS);				\
+	} while (0)
+#endif
 
-#define	STATE_TRANSLATE(s) \
-	(s)->lan.addr.addr32[0] != (s)->gwy.addr.addr32[0] || \
-	((s)->af == AF_INET6 && \
-	((s)->lan.addr.addr32[1] != (s)->gwy.addr.addr32[1] || \
-	(s)->lan.addr.addr32[2] != (s)->gwy.addr.addr32[2] || \
-	(s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \
-	(s)->lan.port != (s)->gwy.port
-
-#define BOUND_IFACE(r, k) \
+#ifdef __FreeBSD__
+#define	BOUND_IFACE(r, k) \
+	((r)->rule_flag & PFRULE_IFBOUND) ? (k) : V_pfi_all
+#else
+#define	BOUND_IFACE(r, k) \
 	((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
+#endif
 
-#define STATE_INC_COUNTERS(s)				\
+#define	STATE_INC_COUNTERS(s)				\
 	do {						\
-		s->rule.ptr->states++;			\
-		if (s->anchor.ptr != NULL)		\
-			s->anchor.ptr->states++;	\
-		if (s->nat_rule.ptr != NULL)		\
-			s->nat_rule.ptr->states++;	\
+		s->rule.ptr->states_cur++;		\
+		s->rule.ptr->states_tot++;		\
+		if (s->anchor.ptr != NULL) {		\
+			s->anchor.ptr->states_cur++;	\
+			s->anchor.ptr->states_tot++;	\
+		}					\
+		if (s->nat_rule.ptr != NULL) {		\
+			s->nat_rule.ptr->states_cur++;	\
+			s->nat_rule.ptr->states_tot++;	\
+		}					\
 	} while (0)
 
-#define STATE_DEC_COUNTERS(s)				\
+#define	STATE_DEC_COUNTERS(s)				\
 	do {						\
 		if (s->nat_rule.ptr != NULL)		\
-			s->nat_rule.ptr->states--;	\
+			s->nat_rule.ptr->states_cur--;	\
 		if (s->anchor.ptr != NULL)		\
-			s->anchor.ptr->states--;	\
-		s->rule.ptr->states--;			\
+			s->anchor.ptr->states_cur--;	\
+		s->rule.ptr->states_cur--;		\
 	} while (0)
 
+static __inline int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
+static __inline int pf_state_compare_key(struct pf_state_key *,
+	struct pf_state_key *);
+static __inline int pf_state_compare_id(struct pf_state *,
+	struct pf_state *);
+
+#ifdef __FreeBSD__
+VNET_DEFINE(struct pf_src_tree,	 	 tree_src_tracking);
+
+VNET_DEFINE(struct pf_state_tree_id,	 tree_id);
+VNET_DEFINE(struct pf_state_queue,	 state_list);
+#else
 struct pf_src_tree tree_src_tracking;
 
 struct pf_state_tree_id tree_id;
 struct pf_state_queue state_list;
-
-#ifdef __FreeBSD__
-static int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
-static int pf_state_compare_lan_ext(struct pf_state *, struct pf_state *);
-static int pf_state_compare_ext_gwy(struct pf_state *, struct pf_state *);
-static int pf_state_compare_id(struct pf_state *, struct pf_state *);
 #endif
 
 RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
-RB_GENERATE(pf_state_tree_lan_ext, pf_state,
-    u.s.entry_lan_ext, pf_state_compare_lan_ext);
-RB_GENERATE(pf_state_tree_ext_gwy, pf_state,
-    u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
+RB_GENERATE(pf_state_tree, pf_state_key, entry, pf_state_compare_key);
 RB_GENERATE(pf_state_tree_id, pf_state,
-    u.s.entry_id, pf_state_compare_id);
+    entry_id, pf_state_compare_id);
 
-#ifdef __FreeBSD__
-static int
-#else
 static __inline int
-#endif
 pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
 {
 	int	diff;
@@ -449,169 +518,6 @@ pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
 	return (0);
 }
 
-#ifdef __FreeBSD__
-static int
-#else
-static __inline int
-#endif
-pf_state_compare_lan_ext(struct pf_state *a, struct pf_state *b)
-{
-	int	diff;
-
-	if ((diff = a->proto - b->proto) != 0)
-		return (diff);
-	if ((diff = a->af - b->af) != 0)
-		return (diff);
-	switch (a->af) {
-#ifdef INET
-	case AF_INET:
-		if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
-			return (1);
-		if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
-			return (-1);
-		if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
-			return (1);
-		if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
-			return (-1);
-		break;
-#endif /* INET */
-#ifdef INET6
-	case AF_INET6:
-		if (a->lan.addr.addr32[3] > b->lan.addr.addr32[3])
-			return (1);
-		if (a->lan.addr.addr32[3] < b->lan.addr.addr32[3])
-			return (-1);
-		if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
-			return (1);
-		if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
-			return (-1);
-		if (a->lan.addr.addr32[2] > b->lan.addr.addr32[2])
-			return (1);
-		if (a->lan.addr.addr32[2] < b->lan.addr.addr32[2])
-			return (-1);
-		if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
-			return (1);
-		if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
-			return (-1);
-		if (a->lan.addr.addr32[1] > b->lan.addr.addr32[1])
-			return (1);
-		if (a->lan.addr.addr32[1] < b->lan.addr.addr32[1])
-			return (-1);
-		if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
-			return (1);
-		if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
-			return (-1);
-		if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
-			return (1);
-		if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
-			return (-1);
-		if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
-			return (1);
-		if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
-			return (-1);
-		break;
-#endif /* INET6 */
-	}
-
-	if ((diff = a->lan.port - b->lan.port) != 0)
-		return (diff);
-	if ((diff = a->ext.port - b->ext.port) != 0)
-		return (diff);
-
-	return (0);
-}
-
-#ifdef __FreeBSD__
-static int
-#else
-static __inline int
-#endif
-pf_state_compare_ext_gwy(struct pf_state *a, struct pf_state *b)
-{
-	int	diff;
-
-	if ((diff = a->proto - b->proto) != 0)
-		return (diff);
-	if ((diff = a->af - b->af) != 0)
-		return (diff);
-	switch (a->af) {
-#ifdef INET
-	case AF_INET:
-		if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
-			return (1);
-		if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
-			return (-1);
-		if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
-			return (1);
-		if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
-			return (-1);
-		break;
-#endif /* INET */
-#ifdef INET6
-	case AF_INET6:
-		if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
-			return (1);
-		if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
-			return (-1);
-		if (a->gwy.addr.addr32[3] > b->gwy.addr.addr32[3])
-			return (1);
-		if (a->gwy.addr.addr32[3] < b->gwy.addr.addr32[3])
-			return (-1);
-		if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
-			return (1);
-		if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
-			return (-1);
-		if (a->gwy.addr.addr32[2] > b->gwy.addr.addr32[2])
-			return (1);
-		if (a->gwy.addr.addr32[2] < b->gwy.addr.addr32[2])
-			return (-1);
-		if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
-			return (1);
-		if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
-			return (-1);
-		if (a->gwy.addr.addr32[1] > b->gwy.addr.addr32[1])
-			return (1);
-		if (a->gwy.addr.addr32[1] < b->gwy.addr.addr32[1])
-			return (-1);
-		if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
-			return (1);
-		if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
-			return (-1);
-		if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
-			return (1);
-		if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
-			return (-1);
-		break;
-#endif /* INET6 */
-	}
-
-	if ((diff = a->ext.port - b->ext.port) != 0)
-		return (diff);
-	if ((diff = a->gwy.port - b->gwy.port) != 0)
-		return (diff);
-
-	return (0);
-}
-
-#ifdef __FreeBSD__
-static int
-#else
-static __inline int
-#endif
-pf_state_compare_id(struct pf_state *a, struct pf_state *b)
-{
-	if (a->id > b->id)
-		return (1);
-	if (a->id < b->id)
-		return (-1);
-	if (a->creatorid > b->creatorid)
-		return (1);
-	if (a->creatorid < b->creatorid)
-		return (-1);
-
-	return (0);
-}
-
 #ifdef INET6
 void
 pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
@@ -632,80 +538,6 @@ pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
 }
 #endif /* INET6 */
 
-struct pf_state *
-pf_find_state_byid(struct pf_state_cmp *key)
-{
-	pf_status.fcounters[FCNT_STATE_SEARCH]++;
-	return (RB_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key));
-}
-
-struct pf_state *
-pf_find_state_recurse(struct pfi_kif *kif, struct pf_state_cmp *key, u_int8_t tree)
-{
-	struct pf_state *s;
-
-	pf_status.fcounters[FCNT_STATE_SEARCH]++;
-
-	switch (tree) {
-	case PF_LAN_EXT:
-		if ((s = RB_FIND(pf_state_tree_lan_ext, &kif->pfik_lan_ext,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		if ((s = RB_FIND(pf_state_tree_lan_ext, &pfi_all->pfik_lan_ext,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		return (NULL);
-	case PF_EXT_GWY:
-		if ((s = RB_FIND(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		if ((s = RB_FIND(pf_state_tree_ext_gwy, &pfi_all->pfik_ext_gwy,
-		    (struct pf_state *)key)) != NULL)
-			return (s);
-		return (NULL);
-	default:
-		panic("pf_find_state_recurse");
-	}
-}
-
-struct pf_state *
-pf_find_state_all(struct pf_state_cmp *key, u_int8_t tree, int *more)
-{
-	struct pf_state *s, *ss = NULL;
-	struct pfi_kif	*kif;
-
-	pf_status.fcounters[FCNT_STATE_SEARCH]++;
-
-	switch (tree) {
-	case PF_LAN_EXT:
-		TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
-			s = RB_FIND(pf_state_tree_lan_ext,
-			    &kif->pfik_lan_ext, (struct pf_state *)key);
-			if (s == NULL)
-				continue;
-			if (more == NULL)
-				return (s);
-			ss = s;
-			(*more)++;
-		}
-		return (ss);
-	case PF_EXT_GWY:
-		TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
-			s = RB_FIND(pf_state_tree_ext_gwy,
-			    &kif->pfik_ext_gwy, (struct pf_state *)key);
-			if (s == NULL)
-				continue;
-			if (more == NULL)
-				return (s);
-			ss = s;
-			(*more)++;
-		}
-		return (ss);
-	default:
-		panic("pf_find_state_all");
-	}
-}
-
 void
 pf_init_threshold(struct pf_threshold *threshold,
     u_int32_t limit, u_int32_t seconds)
@@ -739,7 +571,6 @@ pf_check_threshold(struct pf_threshold *threshold)
 int
 pf_src_connlimit(struct pf_state **state)
 {
-	struct pf_state	*s;
 	int bad = 0;
 
 	(*state)->src_node->conn++;
@@ -749,13 +580,21 @@ pf_src_connlimit(struct pf_state **state)
 	if ((*state)->rule.ptr->max_src_conn &&
 	    (*state)->rule.ptr->max_src_conn <
 	    (*state)->src_node->conn) {
+#ifdef __FreeBSD__
+		V_pf_status.lcounters[LCNT_SRCCONN]++;
+#else
 		pf_status.lcounters[LCNT_SRCCONN]++;
+#endif
 		bad++;
 	}
 
 	if ((*state)->rule.ptr->max_src_conn_rate.limit &&
 	    pf_check_threshold(&(*state)->src_node->conn_rate)) {
+#ifdef __FreeBSD__
+		V_pf_status.lcounters[LCNT_SRCCONNRATE]++;
+#else
 		pf_status.lcounters[LCNT_SRCCONNRATE]++;
+#endif
 		bad++;
 	}
 
@@ -766,16 +605,21 @@ pf_src_connlimit(struct pf_state **state)
 		struct pfr_addr p;
 		u_int32_t	killed = 0;
 
+#ifdef __FreeBSD__
+		V_pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
+		if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 		pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
 		if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 			printf("pf_src_connlimit: blocking address ");
 			pf_print_host(&(*state)->src_node->addr, 0,
-			    (*state)->af);
+			    (*state)->key[PF_SK_WIRE]->af);
 		}
 
 		bzero(&p, sizeof(p));
-		p.pfra_af = (*state)->af;
-		switch ((*state)->af) {
+		p.pfra_af = (*state)->key[PF_SK_WIRE]->af;
+		switch ((*state)->key[PF_SK_WIRE]->af) {
 #ifdef INET
 		case AF_INET:
 			p.pfra_net = 32;
@@ -795,34 +639,51 @@ pf_src_connlimit(struct pf_state **state)
 
 		/* kill existing states if that's required. */
 		if ((*state)->rule.ptr->flush) {
-			pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
+			struct pf_state_key *sk;
+			struct pf_state *st;
 
-			RB_FOREACH(s, pf_state_tree_id, &tree_id) {
+#ifdef __FreeBSD__
+			V_pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
+			RB_FOREACH(st, pf_state_tree_id, &V_tree_id) {
+#else
+			pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
+			RB_FOREACH(st, pf_state_tree_id, &tree_id) {
+#endif
+				sk = st->key[PF_SK_WIRE];
 				/*
 				 * Kill states from this source.  (Only those
 				 * from the same rule if PF_FLUSH_GLOBAL is not
 				 * set)
 				 */
-				if (s->af == (*state)->af &&
+				if (sk->af ==
+				    (*state)->key[PF_SK_WIRE]->af &&
 				    (((*state)->direction == PF_OUT &&
 				    PF_AEQ(&(*state)->src_node->addr,
-				    &s->lan.addr, s->af)) ||
+					&sk->addr[0], sk->af)) ||
 				    ((*state)->direction == PF_IN &&
 				    PF_AEQ(&(*state)->src_node->addr,
-				    &s->ext.addr, s->af))) &&
+					&sk->addr[1], sk->af))) &&
 				    ((*state)->rule.ptr->flush &
 				    PF_FLUSH_GLOBAL ||
-				    (*state)->rule.ptr == s->rule.ptr)) {
-					s->timeout = PFTM_PURGE;
-					s->src.state = s->dst.state =
+				    (*state)->rule.ptr == st->rule.ptr)) {
+					st->timeout = PFTM_PURGE;
+					st->src.state = st->dst.state =
 					    TCPS_CLOSED;
 					killed++;
 				}
 			}
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
 			if (pf_status.debug >= PF_DEBUG_MISC)
+#endif
 				printf(", %u states killed", killed);
 		}
+#ifdef __FreeBSD__
+		if (V_pf_status.debug >= PF_DEBUG_MISC)
+#else
 		if (pf_status.debug >= PF_DEBUG_MISC)
+#endif
 			printf("\n");
 	}
 
@@ -846,18 +707,30 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
 			k.rule.ptr = rule;
 		else
 			k.rule.ptr = NULL;
+#ifdef __FreeBSD__
+		V_pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
+		*sn = RB_FIND(pf_src_tree, &V_tree_src_tracking, &k);
+#else
 		pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
 		*sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
+#endif
 	}
 	if (*sn == NULL) {
 		if (!rule->max_src_nodes ||
 		    rule->src_nodes < rule->max_src_nodes)
-			(*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+			(*sn) = pool_get(&V_pf_src_tree_pl, PR_NOWAIT | PR_ZERO);
+#else
+			(*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT | PR_ZERO);
+#endif
 		else
+#ifdef __FreeBSD__
+			V_pf_status.lcounters[LCNT_SRCNODES]++;
+#else
 			pf_status.lcounters[LCNT_SRCNODES]++;
+#endif
 		if ((*sn) == NULL)
 			return (-1);
-		bzero(*sn, sizeof(struct pf_src_node));
 
 		pf_init_threshold(&(*sn)->conn_rate,
 		    rule->max_src_conn_rate.limit,
@@ -871,296 +744,805 @@ pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
 			(*sn)->rule.ptr = NULL;
 		PF_ACPY(&(*sn)->addr, src, af);
 		if (RB_INSERT(pf_src_tree,
+#ifdef __FreeBSD__
+		    &V_tree_src_tracking, *sn) != NULL) {
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 		    &tree_src_tracking, *sn) != NULL) {
 			if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 				printf("pf: src_tree insert failed: ");
 				pf_print_host(&(*sn)->addr, 0, af);
 				printf("\n");
 			}
+#ifdef __FreeBSD__
+			pool_put(&V_pf_src_tree_pl, *sn);
+#else
 			pool_put(&pf_src_tree_pl, *sn);
+#endif
 			return (-1);
 		}
 		(*sn)->creation = time_second;
 		(*sn)->ruletype = rule->action;
 		if ((*sn)->rule.ptr != NULL)
 			(*sn)->rule.ptr->src_nodes++;
+#ifdef __FreeBSD__
+		V_pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
+		V_pf_status.src_nodes++;
+#else
 		pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
 		pf_status.src_nodes++;
+#endif
 	} else {
 		if (rule->max_src_states &&
 		    (*sn)->states >= rule->max_src_states) {
+#ifdef __FreeBSD__
+			V_pf_status.lcounters[LCNT_SRCSTATES]++;
+#else
 			pf_status.lcounters[LCNT_SRCSTATES]++;
+#endif
 			return (-1);
 		}
 	}
 	return (0);
 }
 
-int
-pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
+/* state table stuff */
+
+static __inline int
+pf_state_compare_key(struct pf_state_key *a, struct pf_state_key *b)
 {
-	/* Thou MUST NOT insert multiple duplicate keys */
-	state->u.s.kif = kif;
-	if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) {
-		if (pf_status.debug >= PF_DEBUG_MISC) {
-			printf("pf: state insert failed: tree_lan_ext");
-			printf(" lan: ");
-			pf_print_host(&state->lan.addr, state->lan.port,
-			    state->af);
-			printf(" gwy: ");
-			pf_print_host(&state->gwy.addr, state->gwy.port,
-			    state->af);
-			printf(" ext: ");
-			pf_print_host(&state->ext.addr, state->ext.port,
-			    state->af);
-			if (state->sync_flags & PFSTATE_FROMSYNC)
-				printf(" (from sync)");
-			printf("\n");
-		}
-		return (-1);
+	int	diff;
+
+	if ((diff = a->proto - b->proto) != 0)
+		return (diff);
+	if ((diff = a->af - b->af) != 0)
+		return (diff);
+	switch (a->af) {
+#ifdef INET
+	case AF_INET:
+		if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
+			return (1);
+		if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
+			return (-1);
+		if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
+			return (1);
+		if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
+			return (-1);
+		break;
+#endif /* INET */
+#ifdef INET6
+	case AF_INET6:
+		if (a->addr[0].addr32[3] > b->addr[0].addr32[3])
+			return (1);
+		if (a->addr[0].addr32[3] < b->addr[0].addr32[3])
+			return (-1);
+		if (a->addr[1].addr32[3] > b->addr[1].addr32[3])
+			return (1);
+		if (a->addr[1].addr32[3] < b->addr[1].addr32[3])
+			return (-1);
+		if (a->addr[0].addr32[2] > b->addr[0].addr32[2])
+			return (1);
+		if (a->addr[0].addr32[2] < b->addr[0].addr32[2])
+			return (-1);
+		if (a->addr[1].addr32[2] > b->addr[1].addr32[2])
+			return (1);
+		if (a->addr[1].addr32[2] < b->addr[1].addr32[2])
+			return (-1);
+		if (a->addr[0].addr32[1] > b->addr[0].addr32[1])
+			return (1);
+		if (a->addr[0].addr32[1] < b->addr[0].addr32[1])
+			return (-1);
+		if (a->addr[1].addr32[1] > b->addr[1].addr32[1])
+			return (1);
+		if (a->addr[1].addr32[1] < b->addr[1].addr32[1])
+			return (-1);
+		if (a->addr[0].addr32[0] > b->addr[0].addr32[0])
+			return (1);
+		if (a->addr[0].addr32[0] < b->addr[0].addr32[0])
+			return (-1);
+		if (a->addr[1].addr32[0] > b->addr[1].addr32[0])
+			return (1);
+		if (a->addr[1].addr32[0] < b->addr[1].addr32[0])
+			return (-1);
+		break;
+#endif /* INET6 */
 	}
 
-	if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) {
-		if (pf_status.debug >= PF_DEBUG_MISC) {
-			printf("pf: state insert failed: tree_ext_gwy");
-			printf(" lan: ");
-			pf_print_host(&state->lan.addr, state->lan.port,
-			    state->af);
-			printf(" gwy: ");
-			pf_print_host(&state->gwy.addr, state->gwy.port,
-			    state->af);
-			printf(" ext: ");
-			pf_print_host(&state->ext.addr, state->ext.port,
-			    state->af);
-			if (state->sync_flags & PFSTATE_FROMSYNC)
-				printf(" (from sync)");
-			printf("\n");
-		}
-		RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
+	if ((diff = a->port[0] - b->port[0]) != 0)
+		return (diff);
+	if ((diff = a->port[1] - b->port[1]) != 0)
+		return (diff);
+
+	return (0);
+}
+
+static __inline int
+pf_state_compare_id(struct pf_state *a, struct pf_state *b)
+{
+	if (a->id > b->id)
+		return (1);
+	if (a->id < b->id)
+		return (-1);
+	if (a->creatorid > b->creatorid)
+		return (1);
+	if (a->creatorid < b->creatorid)
 		return (-1);
-	}
 
-	if (state->id == 0 && state->creatorid == 0) {
-		state->id = htobe64(pf_status.stateid++);
-		state->creatorid = pf_status.hostid;
-	}
-	if (RB_INSERT(pf_state_tree_id, &tree_id, state) != NULL) {
-		if (pf_status.debug >= PF_DEBUG_MISC) {
+	return (0);
+}
+
+int
+pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int idx)
+{
+	struct pf_state_item	*si;
+	struct pf_state_key	*cur;
+	struct pf_state		*olds = NULL;
+
 #ifdef __FreeBSD__
-			printf("pf: state insert failed: "
-			    "id: %016llx creatorid: %08x",
-			    (long long)be64toh(state->id),
-			    ntohl(state->creatorid));
+	KASSERT(s->key[idx] == NULL, ("%s: key is null!", __FUNCTION__));
 #else
-			printf("pf: state insert failed: "
-			    "id: %016llx creatorid: %08x",
-			    betoh64(state->id), ntohl(state->creatorid));
+	KASSERT(s->key[idx] == NULL);	/* XXX handle this? */
 #endif
-			if (state->sync_flags & PFSTATE_FROMSYNC)
-				printf(" (from sync)");
-			printf("\n");
-		}
-		RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
-		RB_REMOVE(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state);
+
+#ifdef __FreeBSD__
+	if ((cur = RB_INSERT(pf_state_tree, &V_pf_statetbl, sk)) != NULL) {
+#else
+	if ((cur = RB_INSERT(pf_state_tree, &pf_statetbl, sk)) != NULL) {
+#endif
+		/* key exists. check for same kif, if none, add to key */
+		TAILQ_FOREACH(si, &cur->states, entry)
+			if (si->s->kif == s->kif &&
+			    si->s->direction == s->direction) {
+				if (sk->proto == IPPROTO_TCP &&
+				    si->s->src.state >= TCPS_FIN_WAIT_2 &&
+				    si->s->dst.state >= TCPS_FIN_WAIT_2) {
+					si->s->src.state = si->s->dst.state =
+					    TCPS_CLOSED;
+					/* unlink late or sks can go away */
+					olds = si->s;
+				} else {
+#ifdef __FreeBSD__
+					if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+					if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
+						printf("pf: %s key attach "
+						    "failed on %s: ",
+						    (idx == PF_SK_WIRE) ?
+						    "wire" : "stack",
+						    s->kif->pfik_name);
+						pf_print_state_parts(s,
+						    (idx == PF_SK_WIRE) ?
+						    sk : NULL,
+						    (idx == PF_SK_STACK) ?
+						    sk : NULL);
+						printf(", existing: ");
+						pf_print_state_parts(si->s,
+						    (idx == PF_SK_WIRE) ?
+						    sk : NULL,
+						    (idx == PF_SK_STACK) ?
+						    sk : NULL);
+						printf("\n");
+					}
+#ifdef __FreeBSD__
+					pool_put(&V_pf_state_key_pl, sk);
+#else
+					pool_put(&pf_state_key_pl, sk);
+#endif
+					return (-1);	/* collision! */
+				}
+			}
+#ifdef __FreeBSD__
+		pool_put(&V_pf_state_key_pl, sk);
+#else
+		pool_put(&pf_state_key_pl, sk);
+#endif
+		s->key[idx] = cur;
+	} else
+		s->key[idx] = sk;
+
+#ifdef __FreeBSD__
+	if ((si = pool_get(&V_pf_state_item_pl, PR_NOWAIT)) == NULL) {
+#else
+	if ((si = pool_get(&pf_state_item_pl, PR_NOWAIT)) == NULL) {
+#endif
+		pf_state_key_detach(s, idx);
 		return (-1);
 	}
-	TAILQ_INSERT_TAIL(&state_list, state, u.s.entry_list);
-	pf_status.fcounters[FCNT_STATE_INSERT]++;
-	pf_status.states++;
-	pfi_kif_ref(kif, PFI_KIF_REF_STATE);
-#if NPFSYNC
-	pfsync_insert_state(state);
+	si->s = s;
+
+	/* list is sorted, if-bound states before floating */
+#ifdef __FreeBSD__
+	if (s->kif == V_pfi_all)
+#else
+	if (s->kif == pfi_all)
 #endif
+		TAILQ_INSERT_TAIL(&s->key[idx]->states, si, entry);
+	else
+		TAILQ_INSERT_HEAD(&s->key[idx]->states, si, entry);
+
+	if (olds)
+		pf_unlink_state(olds);
+
 	return (0);
 }
 
 void
-pf_purge_thread(void *v)
+pf_detach_state(struct pf_state *s)
 {
-	int nloops = 0, s;
-#ifdef __FreeBSD__
-	int locked;
-#endif
+	if (s->key[PF_SK_WIRE] == s->key[PF_SK_STACK])
+		s->key[PF_SK_WIRE] = NULL;
 
-	for (;;) {
-		tsleep(pf_purge_thread, PWAIT, "pftm", 1 * hz);
+	if (s->key[PF_SK_STACK] != NULL)
+		pf_state_key_detach(s, PF_SK_STACK);
 
-#ifdef __FreeBSD__
-		sx_slock(&pf_consistency_lock);
-		PF_LOCK();
-		locked = 0;
+	if (s->key[PF_SK_WIRE] != NULL)
+		pf_state_key_detach(s, PF_SK_WIRE);
+}
 
-		if (pf_end_threads) {
-			PF_UNLOCK();
-			sx_sunlock(&pf_consistency_lock);
-			sx_xlock(&pf_consistency_lock);
-			PF_LOCK();
-			pf_purge_expired_states(pf_status.states, 1);
-			pf_purge_expired_fragments();
-			pf_purge_expired_src_nodes(1);
-			pf_end_threads++;
+void
+pf_state_key_detach(struct pf_state *s, int idx)
+{
+	struct pf_state_item	*si;
 
-			sx_xunlock(&pf_consistency_lock);
-			PF_UNLOCK();
-			wakeup(pf_purge_thread);
-			kproc_exit(0);
-		}
-#endif
-		s = splsoftnet();
+	si = TAILQ_FIRST(&s->key[idx]->states);
+	while (si && si->s != s)
+	    si = TAILQ_NEXT(si, entry);
 
-		/* process a fraction of the state table every second */
+	if (si) {
+		TAILQ_REMOVE(&s->key[idx]->states, si, entry);
 #ifdef __FreeBSD__
-		if(!pf_purge_expired_states(1 + (pf_status.states
-		    / pf_default_rule.timeout[PFTM_INTERVAL]), 0)) {
-			PF_UNLOCK();
-			sx_sunlock(&pf_consistency_lock);
-			sx_xlock(&pf_consistency_lock);
-			PF_LOCK();
-			locked = 1;
-
-			pf_purge_expired_states(1 + (pf_status.states
-			    / pf_default_rule.timeout[PFTM_INTERVAL]), 1);
-		}
+		pool_put(&V_pf_state_item_pl, si);
 #else
-		pf_purge_expired_states(1 + (pf_status.states
-		    / pf_default_rule.timeout[PFTM_INTERVAL]));
+		pool_put(&pf_state_item_pl, si);
 #endif
+	}
 
-		/* purge other expired types every PFTM_INTERVAL seconds */
-		if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
-			pf_purge_expired_fragments();
-			if (!pf_purge_expired_src_nodes(locked)) {
-				PF_UNLOCK();
-				sx_sunlock(&pf_consistency_lock);
-				sx_xlock(&pf_consistency_lock);
-				PF_LOCK();
-				locked = 1;
-				pf_purge_expired_src_nodes(1);
-			}
-			nloops = 0;
-		}
-
-		splx(s);
+	if (TAILQ_EMPTY(&s->key[idx]->states)) {
 #ifdef __FreeBSD__
-		PF_UNLOCK();
-		if (locked)
-			sx_xunlock(&pf_consistency_lock);
-		else
-			sx_sunlock(&pf_consistency_lock);
+		RB_REMOVE(pf_state_tree, &V_pf_statetbl, s->key[idx]);
+#else
+		RB_REMOVE(pf_state_tree, &pf_statetbl, s->key[idx]);
+#endif
+		if (s->key[idx]->reverse)
+			s->key[idx]->reverse->reverse = NULL;
+#ifdef __FreeBSD__
+	/* XXX: implement this */
+#else
+		if (s->key[idx]->inp)
+			s->key[idx]->inp->inp_pf_sk = NULL;
+#endif
+#ifdef __FreeBSD__
+		pool_put(&V_pf_state_key_pl, s->key[idx]);
+#else
+		pool_put(&pf_state_key_pl, s->key[idx]);
 #endif
 	}
+	s->key[idx] = NULL;
 }
 
-u_int32_t
-pf_state_expires(const struct pf_state *state)
+struct pf_state_key *
+pf_alloc_state_key(int pool_flags)
 {
-	u_int32_t	timeout;
-	u_int32_t	start;
-	u_int32_t	end;
-	u_int32_t	states;
+	struct pf_state_key	*sk;
 
-	/* handle all PFTM_* > PFTM_MAX here */
-	if (state->timeout == PFTM_PURGE)
-		return (time_second);
-	if (state->timeout == PFTM_UNTIL_PACKET)
-		return (0);
-#ifdef __FreeBSD__	
-	KASSERT(state->timeout != PFTM_UNLINKED,
-	    ("pf_state_expires: timeout == PFTM_UNLINKED"));
-	KASSERT((state->timeout < PFTM_MAX), 
-	    ("pf_state_expires: timeout > PFTM_MAX"));
+#ifdef __FreeBSD__
+	if ((sk = pool_get(&V_pf_state_key_pl, pool_flags)) == NULL)
 #else
-	KASSERT(state->timeout != PFTM_UNLINKED);
-	KASSERT(state->timeout < PFTM_MAX);
+	if ((sk = pool_get(&pf_state_key_pl, pool_flags)) == NULL)
 #endif
-	timeout = state->rule.ptr->timeout[state->timeout];
-	if (!timeout)
-		timeout = pf_default_rule.timeout[state->timeout];
-	start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
-	if (start) {
-		end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
-		states = state->rule.ptr->states;
+		return (NULL);
+	TAILQ_INIT(&sk->states);
+
+	return (sk);
+}
+
+int
+pf_state_key_setup(struct pf_pdesc *pd, struct pf_rule *nr,
+	struct pf_state_key **skw, struct pf_state_key **sks,
+	struct pf_state_key **skp, struct pf_state_key **nkp,
+	struct pf_addr *saddr, struct pf_addr *daddr,
+	u_int16_t sport, u_int16_t dport)
+{
+#ifdef __FreeBSD__
+	KASSERT((*skp == NULL && *nkp == NULL),
+		("%s: skp == NULL && nkp == NULL", __FUNCTION__));
+#else
+	KASSERT((*skp == NULL && *nkp == NULL));
+#endif
+
+	if ((*skp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
+		return (ENOMEM);
+
+	PF_ACPY(&(*skp)->addr[pd->sidx], saddr, pd->af);
+	PF_ACPY(&(*skp)->addr[pd->didx], daddr, pd->af);
+	(*skp)->port[pd->sidx] = sport;
+	(*skp)->port[pd->didx] = dport;
+	(*skp)->proto = pd->proto;
+	(*skp)->af = pd->af;
+
+	if (nr != NULL) {
+		if ((*nkp = pf_alloc_state_key(PR_NOWAIT | PR_ZERO)) == NULL)
+			return (ENOMEM); /* caller must handle cleanup */
+
+		/* XXX maybe just bcopy and TAILQ_INIT(&(*nkp)->states) */
+		PF_ACPY(&(*nkp)->addr[0], &(*skp)->addr[0], pd->af);
+		PF_ACPY(&(*nkp)->addr[1], &(*skp)->addr[1], pd->af);
+		(*nkp)->port[0] = (*skp)->port[0];
+		(*nkp)->port[1] = (*skp)->port[1];
+		(*nkp)->proto = pd->proto;
+		(*nkp)->af = pd->af;
+	} else
+		*nkp = *skp;
+
+	if (pd->dir == PF_IN) {
+		*skw = *skp;
+		*sks = *nkp;
 	} else {
-		start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
-		end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
-		states = pf_status.states;
-	}
-	if (end && states > start && start < end) {
-		if (states < end)
-			return (state->expire + timeout * (end - states) /
-			    (end - start));
-		else
-			return (time_second);
+		*sks = *skp;
+		*skw = *nkp;
 	}
-	return (state->expire + timeout);
+	return (0);
 }
 
-#ifdef __FreeBSD__
+
 int
-pf_purge_expired_src_nodes(int waslocked)
-#else
-void
-pf_purge_expired_src_nodes(int waslocked)
-#endif
+pf_state_insert(struct pfi_kif *kif, struct pf_state_key *skw,
+    struct pf_state_key *sks, struct pf_state *s)
 {
-	 struct pf_src_node		*cur, *next;
-	 int				 locked = waslocked;
+#ifndef __FreeBSD__
+	splassert(IPL_SOFTNET);
+#endif
 
-	 for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
-		 next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
+	s->kif = kif;
 
-		 if (cur->states <= 0 && cur->expire <= time_second) {
-			 if (! locked) {
+	if (skw == sks) {
+		if (pf_state_key_attach(skw, s, PF_SK_WIRE))
+			return (-1);
+		s->key[PF_SK_STACK] = s->key[PF_SK_WIRE];
+	} else {
+		if (pf_state_key_attach(skw, s, PF_SK_WIRE)) {
 #ifdef __FreeBSD__
-				 if (!sx_try_upgrade(&pf_consistency_lock))
-				 	return (0);
+			pool_put(&V_pf_state_key_pl, sks);
 #else
-				 rw_enter_write(&pf_consistency_lock);
+			pool_put(&pf_state_key_pl, sks);
 #endif
-			 	 next = RB_NEXT(pf_src_tree,
-				     &tree_src_tracking, cur);
-				 locked = 1;
-			 }
-			 if (cur->rule.ptr != NULL) {
-				 cur->rule.ptr->src_nodes--;
-				 if (cur->rule.ptr->states <= 0 &&
-				     cur->rule.ptr->max_src_nodes <= 0)
-					 pf_rm_rule(NULL, cur->rule.ptr);
-			 }
-			 RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
-			 pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-			 pf_status.src_nodes--;
-			 pool_put(&pf_src_tree_pl, cur);
-		 }
-	 }
+			return (-1);
+		}
+		if (pf_state_key_attach(sks, s, PF_SK_STACK)) {
+			pf_state_key_detach(s, PF_SK_WIRE);
+			return (-1);
+		}
+	}
 
-	 if (locked && !waslocked)
+	if (s->id == 0 && s->creatorid == 0) {
 #ifdef __FreeBSD__
-		sx_downgrade(&pf_consistency_lock);
+		s->id = htobe64(V_pf_status.stateid++);
+		s->creatorid = V_pf_status.hostid;
 #else
-		rw_exit_write(&pf_consistency_lock);
+		s->id = htobe64(pf_status.stateid++);
+		s->creatorid = pf_status.hostid;
 #endif
-
+	}
 #ifdef __FreeBSD__
-	return (1);
+	if (RB_INSERT(pf_state_tree_id, &V_tree_id, s) != NULL) {
+		if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+	if (RB_INSERT(pf_state_tree_id, &tree_id, s) != NULL) {
+		if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
+			printf("pf: state insert failed: "
+			    "id: %016llx creatorid: %08x",
+#ifdef __FreeBSD__
+			    (unsigned long long)betoh64(s->id), ntohl(s->creatorid));
+#else
+			    betoh64(s->id), ntohl(s->creatorid));
+#endif
+			printf("\n");
+		}
+		pf_detach_state(s);
+		return (-1);
+	}
+#ifdef __FreeBSD__
+	TAILQ_INSERT_TAIL(&V_state_list, s, entry_list);
+	V_pf_status.fcounters[FCNT_STATE_INSERT]++;
+	V_pf_status.states++;
+#else
+	TAILQ_INSERT_TAIL(&state_list, s, entry_list);
+	pf_status.fcounters[FCNT_STATE_INSERT]++;
+	pf_status.states++;
+#endif
+	pfi_kif_ref(kif, PFI_KIF_REF_STATE);
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+	if (pfsync_insert_state_ptr != NULL)
+		pfsync_insert_state_ptr(s);
+#else
+	pfsync_insert_state(s);
 #endif
+#endif
+	return (0);
 }
 
-void
-pf_src_tree_remove_state(struct pf_state *s)
+struct pf_state *
+pf_find_state_byid(struct pf_state_cmp *key)
 {
-	u_int32_t timeout;
+#ifdef __FreeBSD__
+	V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
 
-	if (s->src_node != NULL) {
-		if (s->proto == IPPROTO_TCP) {
-			if (s->src.tcp_est)
-				--s->src_node->conn;
-		}
+	return (RB_FIND(pf_state_tree_id, &V_tree_id, (struct pf_state *)key));
+#else
+	pf_status.fcounters[FCNT_STATE_SEARCH]++;
+
+	return (RB_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key));
+#endif
+}
+
+/* XXX debug function, intended to be removed one day */
+int
+pf_compare_state_keys(struct pf_state_key *a, struct pf_state_key *b,
+    struct pfi_kif *kif, u_int dir)
+{
+	/* a (from hdr) and b (new) must be exact opposites of each other */
+	if (a->af == b->af && a->proto == b->proto &&
+	    PF_AEQ(&a->addr[0], &b->addr[1], a->af) &&
+	    PF_AEQ(&a->addr[1], &b->addr[0], a->af) &&
+	    a->port[0] == b->port[1] &&
+	    a->port[1] == b->port[0])
+		return (0);
+	else {
+		/* mismatch. must not happen. */
+		printf("pf: state key linking mismatch! dir=%s, "
+		    "if=%s, stored af=%u, a0: ",
+		    dir == PF_OUT ? "OUT" : "IN", kif->pfik_name, a->af);
+		pf_print_host(&a->addr[0], a->port[0], a->af);
+		printf(", a1: ");
+		pf_print_host(&a->addr[1], a->port[1], a->af);
+		printf(", proto=%u", a->proto);
+		printf(", found af=%u, a0: ", b->af);
+		pf_print_host(&b->addr[0], b->port[0], b->af);
+		printf(", a1: ");
+		pf_print_host(&b->addr[1], b->port[1], b->af);
+		printf(", proto=%u", b->proto);
+		printf(".\n");
+		return (-1);
+	}
+}
+
+struct pf_state *
+#ifdef __FreeBSD__
+pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir,
+    struct mbuf *m, struct pf_mtag *pftag)
+#else
+pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir,
+    struct mbuf *m)
+#endif
+{
+	struct pf_state_key	*sk;
+	struct pf_state_item	*si;
+
+#ifdef __FreeBSD__
+	V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
+#else
+	pf_status.fcounters[FCNT_STATE_SEARCH]++;
+#endif
+
+#ifdef __FreeBSD__
+	if (dir == PF_OUT && pftag->statekey &&
+	    ((struct pf_state_key *)pftag->statekey)->reverse)
+		sk = ((struct pf_state_key *)pftag->statekey)->reverse;
+	else {
+#ifdef __FreeBSD__
+		if ((sk = RB_FIND(pf_state_tree, &V_pf_statetbl,
+#else
+		if ((sk = RB_FIND(pf_state_tree, &pf_statetbl,
+#endif
+		    (struct pf_state_key *)key)) == NULL)
+			return (NULL);
+		if (dir == PF_OUT && pftag->statekey &&
+		    pf_compare_state_keys(pftag->statekey, sk,
+		    kif, dir) == 0) {
+			((struct pf_state_key *)
+			    pftag->statekey)->reverse = sk;
+			sk->reverse = pftag->statekey;
+		}
+	}
+#else
+	if (dir == PF_OUT && m->m_pkthdr.pf.statekey &&
+	    ((struct pf_state_key *)m->m_pkthdr.pf.statekey)->reverse)
+		sk = ((struct pf_state_key *)m->m_pkthdr.pf.statekey)->reverse;
+	else {
+#ifdef __FreeBSD__
+		if ((sk = RB_FIND(pf_state_tree, &V_pf_statetbl,
+#else
+		if ((sk = RB_FIND(pf_state_tree, &pf_statetbl,
+#endif
+		    (struct pf_state_key *)key)) == NULL)
+			return (NULL);
+		if (dir == PF_OUT && m->m_pkthdr.pf.statekey &&
+		    pf_compare_state_keys(m->m_pkthdr.pf.statekey, sk,
+		    kif, dir) == 0) {
+			((struct pf_state_key *)
+			    m->m_pkthdr.pf.statekey)->reverse = sk;
+			sk->reverse = m->m_pkthdr.pf.statekey;
+		}
+	}
+#endif
+
+	if (dir == PF_OUT)
+#ifdef __FreeBSD__
+		pftag->statekey = NULL;
+#else
+		m->m_pkthdr.pf.statekey = NULL;
+#endif
+
+	/* list is sorted, if-bound states before floating ones */
+	TAILQ_FOREACH(si, &sk->states, entry)
+#ifdef __FreeBSD__
+		if ((si->s->kif == V_pfi_all || si->s->kif == kif) &&
+#else
+		if ((si->s->kif == pfi_all || si->s->kif == kif) &&
+#endif
+		    sk == (dir == PF_IN ? si->s->key[PF_SK_WIRE] :
+		    si->s->key[PF_SK_STACK]))
+			return (si->s);
+
+	return (NULL);
+}
+
+struct pf_state *
+pf_find_state_all(struct pf_state_key_cmp *key, u_int dir, int *more)
+{
+	struct pf_state_key	*sk;
+	struct pf_state_item	*si, *ret = NULL;
+
+#ifdef __FreeBSD__
+	V_pf_status.fcounters[FCNT_STATE_SEARCH]++;
+#else
+	pf_status.fcounters[FCNT_STATE_SEARCH]++;
+#endif
+
+#ifdef __FreeBSD__
+	sk = RB_FIND(pf_state_tree, &V_pf_statetbl, (struct pf_state_key *)key);
+#else
+	sk = RB_FIND(pf_state_tree, &pf_statetbl, (struct pf_state_key *)key);
+#endif
+	if (sk != NULL) {
+		TAILQ_FOREACH(si, &sk->states, entry)
+			if (dir == PF_INOUT ||
+			    (sk == (dir == PF_IN ? si->s->key[PF_SK_WIRE] :
+			    si->s->key[PF_SK_STACK]))) {
+				if (more == NULL)
+					return (si->s);
+
+				if (ret)
+					(*more)++;
+				else
+					ret = si;
+			}
+	}
+	return (ret ? ret->s : NULL);
+}
+
+/* END state table stuff */
+
+
+void
+pf_purge_thread(void *v)
+{
+	int nloops = 0, s;
+#ifdef __FreeBSD__
+	int locked;
+#endif
+
+	CURVNET_SET((struct vnet *)v);
+
+	for (;;) {
+		tsleep(pf_purge_thread, PWAIT, "pftm", 1 * hz);
+
+#ifdef __FreeBSD__
+	sx_slock(&V_pf_consistency_lock);
+	PF_LOCK();
+	locked = 0;
+
+	if (V_pf_end_threads) {
+		PF_UNLOCK();
+		sx_sunlock(&V_pf_consistency_lock);
+		sx_xlock(&V_pf_consistency_lock);
+		PF_LOCK();
+
+		pf_purge_expired_states(V_pf_status.states, 1);
+		pf_purge_expired_fragments();
+		pf_purge_expired_src_nodes(1);
+		V_pf_end_threads++;
+
+		sx_xunlock(&V_pf_consistency_lock);
+		PF_UNLOCK();
+		wakeup(pf_purge_thread);
+		kproc_exit(0);
+	}
+#endif
+		s = splsoftnet();
+
+		/* process a fraction of the state table every second */
+#ifdef __FreeBSD__
+	if (!pf_purge_expired_states(1 + (V_pf_status.states /
+	    V_pf_default_rule.timeout[PFTM_INTERVAL]), 0)) {
+		PF_UNLOCK();
+		sx_sunlock(&V_pf_consistency_lock);
+		sx_xlock(&V_pf_consistency_lock);
+		PF_LOCK();
+		locked = 1;
+
+		pf_purge_expired_states(1 + (V_pf_status.states /
+		    V_pf_default_rule.timeout[PFTM_INTERVAL]), 1);
+	}
+#else
+		pf_purge_expired_states(1 + (pf_status.states
+		    / pf_default_rule.timeout[PFTM_INTERVAL]));
+#endif
+
+		/* purge other expired types every PFTM_INTERVAL seconds */
+#ifdef __FreeBSD__
+		if (++nloops >= V_pf_default_rule.timeout[PFTM_INTERVAL]) {
+#else
+		if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
+#endif
+			pf_purge_expired_fragments();
+			pf_purge_expired_src_nodes(0);
+			nloops = 0;
+		}
+
+		splx(s);
+#ifdef __FreeBSD__
+		PF_UNLOCK();
+		if (locked)
+			sx_xunlock(&V_pf_consistency_lock);
+		else
+			sx_sunlock(&V_pf_consistency_lock);
+#endif
+	}
+	CURVNET_RESTORE();
+}
+
+u_int32_t
+pf_state_expires(const struct pf_state *state)
+{
+	u_int32_t	timeout;
+	u_int32_t	start;
+	u_int32_t	end;
+	u_int32_t	states;
+
+	/* handle all PFTM_* > PFTM_MAX here */
+	if (state->timeout == PFTM_PURGE)
+		return (time_second);
+	if (state->timeout == PFTM_UNTIL_PACKET)
+		return (0);
+#ifdef __FreeBSD__
+	KASSERT(state->timeout != PFTM_UNLINKED,
+	    ("pf_state_expires: timeout == PFTM_UNLINKED"));
+	KASSERT((state->timeout < PFTM_MAX), 
+	    ("pf_state_expires: timeout > PFTM_MAX"));
+#else
+	KASSERT(state->timeout != PFTM_UNLINKED);
+	KASSERT(state->timeout < PFTM_MAX);
+#endif
+	timeout = state->rule.ptr->timeout[state->timeout];
+	if (!timeout)
+#ifdef __FreeBSD__
+		timeout = V_pf_default_rule.timeout[state->timeout];
+#else
+		timeout = pf_default_rule.timeout[state->timeout];
+#endif
+	start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
+	if (start) {
+		end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
+		states = state->rule.ptr->states_cur;
+	} else {
+#ifdef __FreeBSD__
+		start = V_pf_default_rule.timeout[PFTM_ADAPTIVE_START];
+		end = V_pf_default_rule.timeout[PFTM_ADAPTIVE_END];
+		states = V_pf_status.states;
+#else
+		start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
+		end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
+		states = pf_status.states;
+#endif
+	}
+	if (end && states > start && start < end) {
+		if (states < end)
+			return (state->expire + timeout * (end - states) /
+			    (end - start));
+		else
+			return (time_second);
+	}
+	return (state->expire + timeout);
+}
+
+#ifdef __FreeBSD__
+int
+pf_purge_expired_src_nodes(int waslocked)
+#else
+void
+pf_purge_expired_src_nodes(int waslocked)
+#endif
+{
+	struct pf_src_node		*cur, *next;
+	int				 locked = waslocked;
+
+#ifdef __FreeBSD__
+	for (cur = RB_MIN(pf_src_tree, &V_tree_src_tracking); cur; cur = next) {
+	next = RB_NEXT(pf_src_tree, &V_tree_src_tracking, cur);
+#else
+	for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
+	next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
+#endif
+
+		if (cur->states <= 0 && cur->expire <= time_second) {
+			if (! locked) {
+#ifdef __FreeBSD__
+				if (!sx_try_upgrade(&V_pf_consistency_lock))
+					return (0);
+#else
+				rw_enter_write(&pf_consistency_lock);
+#endif
+				next = RB_NEXT(pf_src_tree,
+#ifdef __FreeBSD__
+				    &V_tree_src_tracking, cur);
+#else
+				    &tree_src_tracking, cur);
+#endif
+				locked = 1;
+			}
+			if (cur->rule.ptr != NULL) {
+				cur->rule.ptr->src_nodes--;
+				if (cur->rule.ptr->states_cur <= 0 &&
+				    cur->rule.ptr->max_src_nodes <= 0)
+					pf_rm_rule(NULL, cur->rule.ptr);
+			}
+#ifdef __FreeBSD__
+			RB_REMOVE(pf_src_tree, &V_tree_src_tracking, cur);
+			V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+			V_pf_status.src_nodes--;
+			pool_put(&V_pf_src_tree_pl, cur);
+#else
+			RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
+			pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+			pf_status.src_nodes--;
+			pool_put(&pf_src_tree_pl, cur);
+#endif
+		}
+	}
+
+	if (locked && !waslocked)
+#ifdef __FreeBSD__
+	{
+		sx_downgrade(&V_pf_consistency_lock);
+	}
+	return (1);
+#else
+		rw_exit_write(&pf_consistency_lock);
+#endif
+}
+
+void
+pf_src_tree_remove_state(struct pf_state *s)
+{
+	u_int32_t timeout;
+
+	if (s->src_node != NULL) {
+		if (s->src.tcp_est)
+			--s->src_node->conn;
 		if (--s->src_node->states <= 0) {
 			timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
 			if (!timeout)
 				timeout =
+#ifdef __FreeBSD__
+				    V_pf_default_rule.timeout[PFTM_SRC_NODE];
+#else
 				    pf_default_rule.timeout[PFTM_SRC_NODE];
+#endif
 			s->src_node->expire = time_second + timeout;
 		}
 	}
@@ -1169,7 +1551,11 @@ pf_src_tree_remove_state(struct pf_state *s)
 			timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
 			if (!timeout)
 				timeout =
+#ifdef __FreeBSD__
+				    V_pf_default_rule.timeout[PFTM_SRC_NODE];
+#else
 				    pf_default_rule.timeout[PFTM_SRC_NODE];
+#endif
 			s->nat_src_node->expire = time_second + timeout;
 		}
 	}
@@ -1184,29 +1570,49 @@ pf_unlink_state(struct pf_state *cur)
 	if (cur->local_flags & PFSTATE_EXPIRING)
 		return;
 	cur->local_flags |= PFSTATE_EXPIRING;
+#else
+	splassert(IPL_SOFTNET);
 #endif
+
 	if (cur->src.state == PF_TCPS_PROXY_DST) {
+		/* XXX wire key the right one? */
 #ifdef __FreeBSD__
-		pf_send_tcp(NULL, cur->rule.ptr, cur->af,
+		pf_send_tcp(NULL, cur->rule.ptr, cur->key[PF_SK_WIRE]->af,
 #else
-		pf_send_tcp(cur->rule.ptr, cur->af,
+		pf_send_tcp(cur->rule.ptr, cur->key[PF_SK_WIRE]->af,
 #endif
-		    &cur->ext.addr, &cur->lan.addr,
-		    cur->ext.port, cur->lan.port,
+		    &cur->key[PF_SK_WIRE]->addr[1],
+		    &cur->key[PF_SK_WIRE]->addr[0],
+		    cur->key[PF_SK_WIRE]->port[1],
+		    cur->key[PF_SK_WIRE]->port[0],
 		    cur->src.seqhi, cur->src.seqlo + 1,
 		    TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
 	}
-	RB_REMOVE(pf_state_tree_ext_gwy,
-	    &cur->u.s.kif->pfik_ext_gwy, cur);
-	RB_REMOVE(pf_state_tree_lan_ext,
-	    &cur->u.s.kif->pfik_lan_ext, cur);
+#ifdef __FreeBSD__
+	RB_REMOVE(pf_state_tree_id, &V_tree_id, cur);
+#else
 	RB_REMOVE(pf_state_tree_id, &tree_id, cur);
-#if NPFSYNC
-	if (cur->creatorid == pf_status.hostid)
-		pfsync_delete_state(cur);
+#endif
+#if NPFLOW > 0
+	if (cur->state_flags & PFSTATE_PFLOW)
+#ifdef __FreeBSD__
+		if (export_pflow_ptr != NULL)
+			export_pflow_ptr(cur);
+#else
+		export_pflow(cur);
+#endif
+#endif
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+	if (pfsync_delete_state_ptr != NULL)
+		pfsync_delete_state_ptr(cur);
+#else
+	pfsync_delete_state(cur);
+#endif
 #endif
 	cur->timeout = PFTM_UNLINKED;
 	pf_src_tree_remove_state(cur);
+	pf_detach_state(cur);
 }
 
 /* callers should be at splsoftnet and hold the
@@ -1214,10 +1620,17 @@ pf_unlink_state(struct pf_state *cur)
 void
 pf_free_state(struct pf_state *cur)
 {
-#if NPFSYNC
-	if (pfsyncif != NULL &&
-	    (pfsyncif->sc_bulk_send_next == cur ||
-	    pfsyncif->sc_bulk_terminator == cur))
+#ifndef __FreeBSD__
+	splassert(IPL_SOFTNET);
+#endif
+
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+	if (pfsync_state_in_use_ptr != NULL)
+		pfsync_state_in_use_ptr(cur);
+#else
+	if (pfsync_state_in_use(cur))
+#endif
 		return;
 #endif
 #ifdef __FreeBSD__
@@ -1226,24 +1639,34 @@ pf_free_state(struct pf_state *cur)
 #else
 	KASSERT(cur->timeout == PFTM_UNLINKED);
 #endif
-	if (--cur->rule.ptr->states <= 0 &&
+	if (--cur->rule.ptr->states_cur <= 0 &&
 	    cur->rule.ptr->src_nodes <= 0)
 		pf_rm_rule(NULL, cur->rule.ptr);
 	if (cur->nat_rule.ptr != NULL)
-		if (--cur->nat_rule.ptr->states <= 0 &&
+		if (--cur->nat_rule.ptr->states_cur <= 0 &&
 			cur->nat_rule.ptr->src_nodes <= 0)
 			pf_rm_rule(NULL, cur->nat_rule.ptr);
 	if (cur->anchor.ptr != NULL)
-		if (--cur->anchor.ptr->states <= 0)
+		if (--cur->anchor.ptr->states_cur <= 0)
 			pf_rm_rule(NULL, cur->anchor.ptr);
 	pf_normalize_tcp_cleanup(cur);
-	pfi_kif_unref(cur->u.s.kif, PFI_KIF_REF_STATE);
-	TAILQ_REMOVE(&state_list, cur, u.s.entry_list);
+	pfi_kif_unref(cur->kif, PFI_KIF_REF_STATE);
+#ifdef __FreeBSD__
+	TAILQ_REMOVE(&V_state_list, cur, entry_list);
+#else
+	TAILQ_REMOVE(&state_list, cur, entry_list);
+#endif
 	if (cur->tag)
 		pf_tag_unref(cur->tag);
+#ifdef __FreeBSD__
+	pool_put(&V_pf_state_pl, cur);
+	V_pf_status.fcounters[FCNT_STATE_REMOVALS]++;
+	V_pf_status.states--;
+#else
 	pool_put(&pf_state_pl, cur);
 	pf_status.fcounters[FCNT_STATE_REMOVALS]++;
 	pf_status.states--;
+#endif
 }
 
 #ifdef __FreeBSD__
@@ -1257,28 +1680,32 @@ pf_purge_expired_states(u_int32_t maxcheck)
 	static struct pf_state	*cur = NULL;
 	struct pf_state		*next;
 #ifdef __FreeBSD__
-	int 			 locked = waslocked;
+	int			 locked = waslocked;
 #else
-	int 			 locked = 0;
+	int			 locked = 0;
 #endif
 
 	while (maxcheck--) {
 		/* wrap to start of list when we hit the end */
 		if (cur == NULL) {
+#ifdef __FreeBSD__
+			cur = TAILQ_FIRST(&V_state_list);
+#else
 			cur = TAILQ_FIRST(&state_list);
+#endif
 			if (cur == NULL)
 				break;	/* list empty */
 		}
 
 		/* get next state, as cur may get deleted */
-		next = TAILQ_NEXT(cur, u.s.entry_list);
+		next = TAILQ_NEXT(cur, entry_list);
 
 		if (cur->timeout == PFTM_UNLINKED) {
 			/* free unlinked state */
 			if (! locked) {
 #ifdef __FreeBSD__
-				 if (!sx_try_upgrade(&pf_consistency_lock))
-				 	return (0);
+				if (!sx_try_upgrade(&V_pf_consistency_lock))
+					return (0);
 #else
 				rw_enter_write(&pf_consistency_lock);
 #endif
@@ -1290,8 +1717,8 @@ pf_purge_expired_states(u_int32_t maxcheck)
 			pf_unlink_state(cur);
 			if (! locked) {
 #ifdef __FreeBSD__
-				 if (!sx_try_upgrade(&pf_consistency_lock))
-				 	return (0);
+				if (!sx_try_upgrade(&V_pf_consistency_lock))
+					return (0);
 #else
 				rw_enter_write(&pf_consistency_lock);
 #endif
@@ -1304,7 +1731,7 @@ pf_purge_expired_states(u_int32_t maxcheck)
 
 #ifdef __FreeBSD__
 	if (!waslocked && locked)
-		sx_downgrade(&pf_consistency_lock);
+		sx_downgrade(&V_pf_consistency_lock);
 
 	return (1);
 #else
@@ -1318,7 +1745,7 @@ pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw)
 {
 	if (aw->type != PF_ADDR_TABLE)
 		return (0);
-	if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname)) == NULL)
+	if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname, 1)) == NULL)
 		return (1);
 	return (0);
 }
@@ -1365,34 +1792,33 @@ pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
 #ifdef INET6
 	case AF_INET6: {
 		u_int16_t b;
-		u_int8_t i, curstart = 255, curend = 0,
-		    maxstart = 0, maxend = 0;
+		u_int8_t i, curstart, curend, maxstart, maxend;
+		curstart = curend = maxstart = maxend = 255;
 		for (i = 0; i < 8; i++) {
 			if (!addr->addr16[i]) {
 				if (curstart == 255)
 					curstart = i;
-				else
-					curend = i;
+				curend = i;
 			} else {
-				if (curstart) {
-					if ((curend - curstart) >
-					    (maxend - maxstart)) {
-						maxstart = curstart;
-						maxend = curend;
-						curstart = 255;
-					}
+				if ((curend - curstart) >
+				    (maxend - maxstart)) {
+					maxstart = curstart;
+					maxend = curend;
 				}
+				curstart = curend = 255;
 			}
 		}
+		if ((curend - curstart) >
+		    (maxend - maxstart)) {
+			maxstart = curstart;
+			maxend = curend;
+		}
 		for (i = 0; i < 8; i++) {
 			if (i >= maxstart && i <= maxend) {
-				if (maxend != 7) {
-					if (i == maxstart)
-						printf(":");
-				} else {
-					if (i == maxend)
-						printf(":");
-				}
+				if (i == 0)
+					printf(":");
+				if (i == maxend)
+					printf(":");
 			} else {
 				b = ntohs(addr->addr16[i]);
 				printf("%x", b);
@@ -1413,39 +1839,87 @@ pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
 void
 pf_print_state(struct pf_state *s)
 {
-	switch (s->proto) {
+	pf_print_state_parts(s, NULL, NULL);
+}
+
+void
+pf_print_state_parts(struct pf_state *s,
+    struct pf_state_key *skwp, struct pf_state_key *sksp)
+{
+	struct pf_state_key *skw, *sks;
+	u_int8_t proto, dir;
+
+	/* Do our best to fill these, but they're skipped if NULL */
+	skw = skwp ? skwp : (s ? s->key[PF_SK_WIRE] : NULL);
+	sks = sksp ? sksp : (s ? s->key[PF_SK_STACK] : NULL);
+	proto = skw ? skw->proto : (sks ? sks->proto : 0);
+	dir = s ? s->direction : 0;
+
+	switch (proto) {
+	case IPPROTO_IPV4:
+		printf("IPv4");
+		break;
+	case IPPROTO_IPV6:
+		printf("IPv6");
+		break;
 	case IPPROTO_TCP:
-		printf("TCP ");
+		printf("TCP");
 		break;
 	case IPPROTO_UDP:
-		printf("UDP ");
+		printf("UDP");
 		break;
 	case IPPROTO_ICMP:
-		printf("ICMP ");
+		printf("ICMP");
 		break;
 	case IPPROTO_ICMPV6:
-		printf("ICMPV6 ");
+		printf("ICMPv6");
 		break;
 	default:
-		printf("%u ", s->proto);
+		printf("%u", skw->proto);
+		break;
+	}
+	switch (dir) {
+	case PF_IN:
+		printf(" in");
 		break;
+	case PF_OUT:
+		printf(" out");
+		break;
+	}
+	if (skw) {
+		printf(" wire: ");
+		pf_print_host(&skw->addr[0], skw->port[0], skw->af);
+		printf(" ");
+		pf_print_host(&skw->addr[1], skw->port[1], skw->af);
+	}
+	if (sks) {
+		printf(" stack: ");
+		if (sks != skw) {
+			pf_print_host(&sks->addr[0], sks->port[0], sks->af);
+			printf(" ");
+			pf_print_host(&sks->addr[1], sks->port[1], sks->af);
+		} else
+			printf("-");
+	}
+	if (s) {
+		if (proto == IPPROTO_TCP) {
+			printf(" [lo=%u high=%u win=%u modulator=%u",
+			    s->src.seqlo, s->src.seqhi,
+			    s->src.max_win, s->src.seqdiff);
+			if (s->src.wscale && s->dst.wscale)
+				printf(" wscale=%u",
+				    s->src.wscale & PF_WSCALE_MASK);
+			printf("]");
+			printf(" [lo=%u high=%u win=%u modulator=%u",
+			    s->dst.seqlo, s->dst.seqhi,
+			    s->dst.max_win, s->dst.seqdiff);
+			if (s->src.wscale && s->dst.wscale)
+				printf(" wscale=%u",
+				s->dst.wscale & PF_WSCALE_MASK);
+			printf("]");
+		}
+		printf(" %u:%u", s->src.state, s->dst.state);
 	}
-	pf_print_host(&s->lan.addr, s->lan.port, s->af);
-	printf(" ");
-	pf_print_host(&s->gwy.addr, s->gwy.port, s->af);
-	printf(" ");
-	pf_print_host(&s->ext.addr, s->ext.port, s->af);
-	printf(" [lo=%u high=%u win=%u modulator=%u", s->src.seqlo,
-	    s->src.seqhi, s->src.max_win, s->src.seqdiff);
-	if (s->src.wscale && s->dst.wscale)
-		printf(" wscale=%u", s->src.wscale & PF_WSCALE_MASK);
-	printf("]");
-	printf(" [lo=%u high=%u win=%u modulator=%u", s->dst.seqlo,
-	    s->dst.seqhi, s->dst.max_win, s->dst.seqdiff);
-	if (s->src.wscale && s->dst.wscale)
-		printf(" wscale=%u", s->dst.wscale & PF_WSCALE_MASK);
-	printf("]");
-	printf(" %u:%u", s->src.state, s->dst.state);
 }
 
 void
@@ -1528,6 +2002,7 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
 		return (1);
 	switch (aw1->type) {
 	case PF_ADDR_ADDRMASK:
+	case PF_ADDR_RANGE:
 		if (PF_ANEQ(&aw1->v.a.addr, &aw2->v.a.addr, 0))
 			return (1);
 		if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
@@ -1651,12 +2126,13 @@ pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
 	struct pf_addr	oia, ooa;
 
 	PF_ACPY(&oia, ia, af);
-	PF_ACPY(&ooa, oa, af);
+	if (oa)
+		PF_ACPY(&ooa, oa, af);
 
 	/* Change inner protocol port, fix inner protocol checksum. */
 	if (ip != NULL) {
 		u_int16_t	oip = *ip;
-		u_int32_t	opc = 0;	/* make the compiler happy */
+		u_int32_t	opc;
 
 		if (pc != NULL)
 			opc = *pc;
@@ -1700,31 +2176,33 @@ pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
 		break;
 #endif /* INET6 */
 	}
-	/* Change outer ip address, fix outer ip or icmpv6 checksum. */
-	PF_ACPY(oa, na, af);
-	switch (af) {
+	/* Outer ip address, fix outer ip or icmpv6 checksum, if necessary. */
+	if (oa) {
+		PF_ACPY(oa, na, af);
+		switch (af) {
 #ifdef INET
-	case AF_INET:
-		*hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
-		    ooa.addr16[0], oa->addr16[0], 0),
-		    ooa.addr16[1], oa->addr16[1], 0);
-		break;
+		case AF_INET:
+			*hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
+			    ooa.addr16[0], oa->addr16[0], 0),
+			    ooa.addr16[1], oa->addr16[1], 0);
+			break;
 #endif /* INET */
 #ifdef INET6
-	case AF_INET6:
-		*ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
-		    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
-		    pf_cksum_fixup(pf_cksum_fixup(*ic,
-		    ooa.addr16[0], oa->addr16[0], u),
-		    ooa.addr16[1], oa->addr16[1], u),
-		    ooa.addr16[2], oa->addr16[2], u),
-		    ooa.addr16[3], oa->addr16[3], u),
-		    ooa.addr16[4], oa->addr16[4], u),
-		    ooa.addr16[5], oa->addr16[5], u),
-		    ooa.addr16[6], oa->addr16[6], u),
-		    ooa.addr16[7], oa->addr16[7], u);
-		break;
+		case AF_INET6:
+			*ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+			    pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+			    pf_cksum_fixup(pf_cksum_fixup(*ic,
+			    ooa.addr16[0], oa->addr16[0], u),
+			    ooa.addr16[1], oa->addr16[1], u),
+			    ooa.addr16[2], oa->addr16[2], u),
+			    ooa.addr16[3], oa->addr16[3], u),
+			    ooa.addr16[4], oa->addr16[4], u),
+			    ooa.addr16[5], oa->addr16[5], u),
+			    ooa.addr16[6], oa->addr16[6], u),
+			    ooa.addr16[7], oa->addr16[7], u);
+			break;
 #endif /* INET6 */
+		}
 	}
 }
 
@@ -1746,7 +2224,7 @@ pf_modulate_sack(struct mbuf *m, int off, struct pf_pdesc *pd,
 	int copyback = 0, i, olen;
 	struct sackblk sack;
 
-#define TCPOLEN_SACKLEN	(TCPOLEN_SACK + 2)
+#define	TCPOLEN_SACKLEN	(TCPOLEN_SACK + 2)
 	if (hlen < TCPOLEN_SACKLEN ||
 	    !pf_pull_hdr(m, off + sizeof(*th), opts, hlen, NULL, NULL, pd->af))
 		return 0;
@@ -1815,9 +2293,9 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
 #endif /* INET6 */
 	struct tcphdr	*th;
 	char		*opt;
-	struct pf_mtag	*pf_mtag;
-
 #ifdef __FreeBSD__
+	struct pf_mtag  *pf_mtag;
+
 	KASSERT(
 #ifdef INET
 	    af == AF_INET
@@ -1839,7 +2317,7 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
 #ifdef INET6
 	h6 = NULL;
 #endif
-#endif
+#endif /* __FreeBSD__ */
 
 	/* maximum segment size tcp option */
 	tlen = sizeof(struct tcphdr);
@@ -1865,42 +2343,46 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
 		return;
 #ifdef __FreeBSD__
 #ifdef MAC
-	if (replyto)
-		mac_netinet_firewall_reply(replyto, m);
-	else
-		mac_netinet_firewall_send(m);
-#else
-	(void)replyto;
-#endif
+	mac_netinet_firewall_send(m);
 #endif
 	if ((pf_mtag = pf_get_mtag(m)) == NULL) {
 		m_freem(m);
 		return;
 	}
+#endif
 	if (tag)
 #ifdef __FreeBSD__
 		m->m_flags |= M_SKIP_FIREWALL;
+	pf_mtag->tag = rtag;
 #else
-		pf_mtag->flags |= PF_TAG_GENERATED;
+		m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
+	m->m_pkthdr.pf.tag = rtag;
 #endif
 
-	pf_mtag->tag = rtag;
-
 	if (r != NULL && r->rtableid >= 0)
 #ifdef __FreeBSD__
 	{
 		M_SETFIB(m, r->rtableid);
-#endif
 		pf_mtag->rtableid = r->rtableid;
+#else
+		m->m_pkthdr.pf.rtableid = r->rtableid;
+#endif
 #ifdef __FreeBSD__
 	}
 #endif
+
 #ifdef ALTQ
 	if (r != NULL && r->qid) {
+#ifdef __FreeBSD__
 		pf_mtag->qid = r->qid;
+
 		/* add hints for ecn */
-		pf_mtag->af = af;
 		pf_mtag->hdr = mtod(m, struct ip *);
+#else
+		m->m_pkthdr.pf.qid = r->qid;
+		/* add hints for ecn */
+		m->m_pkthdr.pf.hdr = mtod(m, struct ip *);
+#endif
 	}
 #endif /* ALTQ */
 	m->m_data += max_linkhdr;
@@ -1966,18 +2448,19 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
 #ifdef __FreeBSD__
 		h->ip_off = V_path_mtu_discovery ? IP_DF : 0;
 		h->ip_len = len;
+		h->ip_ttl = ttl ? ttl : V_ip_defttl;
 #else
-		h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
 		h->ip_len = htons(len);
+		h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
+		h->ip_ttl = ttl ? ttl : ip_defttl;
 #endif
-		h->ip_ttl = ttl ? ttl : V_ip_defttl;
 		h->ip_sum = 0;
 		if (eh == NULL) {
 #ifdef __FreeBSD__
-			PF_UNLOCK();
-			ip_output(m, (void *)NULL, (void *)NULL, 0,
-			    (void *)NULL, (void *)NULL);
-			PF_LOCK();
+		PF_UNLOCK();
+		ip_output(m, (void *)NULL, (void *)NULL, 0,
+		    (void *)NULL, (void *)NULL);
+		PF_LOCK();
 #else /* ! __FreeBSD__ */
 			ip_output(m, (void *)NULL, (void *)NULL, 0,
 			    (void *)NULL, (void *)NULL);
@@ -2025,23 +2508,23 @@ pf_send_tcp(const struct pf_rule *r, sa_family_t af,
 		ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
 		PF_LOCK();
 #else
-		ip6_output(m, NULL, NULL, 0, NULL, NULL);
+		ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
 #endif
 		break;
 #endif /* INET6 */
 	}
 }
 
-void
+static void
 pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
     struct pf_rule *r)
 {
-	struct pf_mtag	*pf_mtag;
 	struct mbuf	*m0;
 #ifdef __FreeBSD__
 #ifdef INET
 	struct ip *ip;
 #endif
+	struct pf_mtag *pf_mtag;
 #endif
 
 #ifdef __FreeBSD__
@@ -2049,33 +2532,42 @@ pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
 	if (m0 == NULL)
 		return;
 #else
-	m0 = m_copy(m, 0, M_COPYALL);
+	if ((m0 = m_copy(m, 0, M_COPYALL)) == NULL)
+		return;
 #endif
+
+#ifdef __FreeBSD__
 	if ((pf_mtag = pf_get_mtag(m0)) == NULL)
 		return;
-#ifdef __FreeBSD__
 	/* XXX: revisit */
 	m0->m_flags |= M_SKIP_FIREWALL;
 #else
-	pf_mtag->flags |= PF_TAG_GENERATED;
+	m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
 #endif
 
 	if (r->rtableid >= 0)
 #ifdef __FreeBSD__
 	{
 		M_SETFIB(m0, r->rtableid);
-#endif
 		pf_mtag->rtableid = r->rtableid;
+#else
+		m0->m_pkthdr.pf.rtableid = r->rtableid;
+#endif
 #ifdef __FreeBSD__
 	}
 #endif
 
 #ifdef ALTQ
 	if (r->qid) {
+#ifdef __FreeBSD__
 		pf_mtag->qid = r->qid;
 		/* add hints for ecn */
-		pf_mtag->af = af;
 		pf_mtag->hdr = mtod(m0, struct ip *);
+#else
+		m0->m_pkthdr.pf.qid = r->qid;
+		/* add hints for ecn */
+		m0->m_pkthdr.pf.hdr = mtod(m0, struct ip *);
+#endif
 	}
 #endif /* ALTQ */
 
@@ -2155,6 +2647,44 @@ pf_match_addr(u_int8_t n, struct pf_addr *a, struct pf_addr *m,
 	}
 }
 
+/*
+ * Return 1 if b <= a <= e, otherwise return 0.
+ */
+int
+pf_match_addr_range(struct pf_addr *b, struct pf_addr *e,
+    struct pf_addr *a, sa_family_t af)
+{
+	switch (af) {
+#ifdef INET
+	case AF_INET:
+		if ((a->addr32[0] < b->addr32[0]) ||
+		    (a->addr32[0] > e->addr32[0]))
+			return (0);
+		break;
+#endif /* INET */
+#ifdef INET6
+	case AF_INET6: {
+		int	i;
+
+		/* check a >= b */
+		for (i = 0; i < 4; ++i)
+			if (a->addr32[i] > b->addr32[i])
+				break;
+			else if (a->addr32[i] < b->addr32[i])
+				return (0);
+		/* check a <= e */
+		for (i = 0; i < 4; ++i)
+			if (a->addr32[i] < e->addr32[i])
+				break;
+			else if (a->addr32[i] > e->addr32[i])
+				return (0);
+		break;
+	}
+#endif /* INET6 */
+	}
+	return (1);
+}
+
 int
 pf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p)
 {
@@ -2206,88 +2736,80 @@ pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
 	return (pf_match(op, a1, a2, g));
 }
 
-#ifndef __FreeBSD__
-struct pf_mtag *
-pf_find_mtag(struct mbuf *m)
-{
-	struct m_tag	*mtag;
-
-	if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL)
-		return (NULL);
-
-	return ((struct pf_mtag *)(mtag + 1));
-}
-
-struct pf_mtag *
-pf_get_mtag(struct mbuf *m)
-{
-	struct m_tag	*mtag;
-
-	if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL) {
-		mtag = m_tag_get(PACKET_TAG_PF, sizeof(struct pf_mtag),
-		    M_NOWAIT);
-		if (mtag == NULL)
-			return (NULL);
-		bzero(mtag + 1, sizeof(struct pf_mtag));
-		m_tag_prepend(m, mtag);
-	}
-
-	return ((struct pf_mtag *)(mtag + 1));
-}
-#endif
-
 int
-pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_mtag *pf_mtag,
-    int *tag)
+#ifdef __FreeBSD__
+pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag,
+    struct pf_mtag *pf_mtag)
+#else
+pf_match_tag(struct mbuf *m, struct pf_rule *r, int *tag)
+#endif
 {
 	if (*tag == -1)
+#ifdef __FreeBSD__
 		*tag = pf_mtag->tag;
+#else
+		*tag = m->m_pkthdr.pf.tag;
+#endif
 
 	return ((!r->match_tag_not && r->match_tag == *tag) ||
 	    (r->match_tag_not && r->match_tag != *tag));
 }
 
 int
-pf_tag_packet(struct mbuf *m, struct pf_mtag *pf_mtag, int tag, int rtableid)
+#ifdef __FreeBSD__
+pf_tag_packet(struct mbuf *m, int tag, int rtableid,
+    struct pf_mtag *pf_mtag)
+#else
+pf_tag_packet(struct mbuf *m, int tag, int rtableid)
+#endif
 {
 	if (tag <= 0 && rtableid < 0)
 		return (0);
 
-	if (pf_mtag == NULL)
-		if ((pf_mtag = pf_get_mtag(m)) == NULL)
-			return (1);
 	if (tag > 0)
+#ifdef __FreeBSD__
 		pf_mtag->tag = tag;
+#else
+		m->m_pkthdr.pf.tag = tag;
+#endif
 	if (rtableid >= 0)
 #ifdef __FreeBSD__
 	{
 		M_SETFIB(m, rtableid);
-#endif
-		pf_mtag->rtableid = rtableid;
-#ifdef __FreeBSD__
 	}
+#else
+		m->m_pkthdr.pf.rtableid = rtableid;
 #endif
 
 	return (0);
 }
 
-static void
+void
 pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
-    struct pf_rule **r, struct pf_rule **a,  int *match)
+    struct pf_rule **r, struct pf_rule **a, int *match)
 {
 	struct pf_anchor_stackframe	*f;
 
 	(*r)->anchor->match = 0;
 	if (match)
 		*match = 0;
+#ifdef __FreeBSD__
+	if (*depth >= sizeof(V_pf_anchor_stack) /
+	    sizeof(V_pf_anchor_stack[0])) {
+#else
 	if (*depth >= sizeof(pf_anchor_stack) /
 	    sizeof(pf_anchor_stack[0])) {
+#endif
 		printf("pf_step_into_anchor: stack overflow\n");
 		*r = TAILQ_NEXT(*r, entries);
 		return;
 	} else if (*depth == 0 && a != NULL)
 		*a = *r;
+#ifdef __FreeBSD__
+	f = V_pf_anchor_stack + (*depth)++;
+#else
 	f = pf_anchor_stack + (*depth)++;
+#endif
 	f->rs = *rs;
 	f->r = *r;
 	if ((*r)->anchor_wildcard) {
@@ -2316,7 +2838,11 @@ pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
 	do {
 		if (*depth <= 0)
 			break;
+#ifdef __FreeBSD__
+		f = V_pf_anchor_stack + *depth - 1;
+#else
 		f = pf_anchor_stack + *depth - 1;
+#endif
 		if (f->parent != NULL && f->child != NULL) {
 			if (f->child->match ||
 			    (match != NULL && *match)) {
@@ -2337,7 +2863,7 @@ pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
 		if (*depth == 0 && a != NULL)
 			*a = NULL;
 		*rs = f->rs;
-		if (f->r->anchor->match || (match  != NULL && *match))
+		if (f->r->anchor->match || (match != NULL && *match))
 			quick = f->r->quick;
 		*r = TAILQ_NEXT(f->r, entries);
 	} while (*r == NULL);
@@ -2402,627 +2928,68 @@ pf_addr_inc(struct pf_addr *addr, sa_family_t af)
 }
 #endif /* INET6 */
 
-#define mix(a,b,c) \
-	do {					\
-		a -= b; a -= c; a ^= (c >> 13);	\
-		b -= c; b -= a; b ^= (a << 8);	\
-		c -= a; c -= b; c ^= (b >> 13);	\
-		a -= b; a -= c; a ^= (c >> 12);	\
-		b -= c; b -= a; b ^= (a << 16);	\
-		c -= a; c -= b; c ^= (b >> 5);	\
-		a -= b; a -= c; a ^= (c >> 3);	\
-		b -= c; b -= a; b ^= (a << 10);	\
-		c -= a; c -= b; c ^= (b >> 15);	\
-	} while (0)
-
-/*
- * hash function based on bridge_hash in if_bridge.c
- */
-void
-pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
-    struct pf_poolhashkey *key, sa_family_t af)
-{
-	u_int32_t	a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
-
-	switch (af) {
-#ifdef INET
-	case AF_INET:
-		a += inaddr->addr32[0];
-		b += key->key32[1];
-		mix(a, b, c);
-		hash->addr32[0] = c + key->key32[2];
-		break;
-#endif /* INET */
-#ifdef INET6
-	case AF_INET6:
-		a += inaddr->addr32[0];
-		b += inaddr->addr32[2];
-		mix(a, b, c);
-		hash->addr32[0] = c;
-		a += inaddr->addr32[1];
-		b += inaddr->addr32[3];
-		c += key->key32[1];
-		mix(a, b, c);
-		hash->addr32[1] = c;
-		a += inaddr->addr32[2];
-		b += inaddr->addr32[1];
-		c += key->key32[2];
-		mix(a, b, c);
-		hash->addr32[2] = c;
-		a += inaddr->addr32[3];
-		b += inaddr->addr32[0];
-		c += key->key32[3];
-		mix(a, b, c);
-		hash->addr32[3] = c;
-		break;
-#endif /* INET6 */
-	}
-}
-
 int
-pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
-    struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
+#ifdef __FreeBSD__
+pf_socket_lookup(int direction, struct pf_pdesc *pd, struct inpcb *inp_arg)
+#else
+pf_socket_lookup(int direction, struct pf_pdesc *pd)
+#endif
 {
-	unsigned char		 hash[16];
-	struct pf_pool		*rpool = &r->rpool;
-	struct pf_addr		*raddr = &rpool->cur->addr.v.a.addr;
-	struct pf_addr		*rmask = &rpool->cur->addr.v.a.mask;
-	struct pf_pooladdr	*acur = rpool->cur;
-	struct pf_src_node	 k;
-
-	if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
-	    (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
-		k.af = af;
-		PF_ACPY(&k.addr, saddr, af);
-		if (r->rule_flag & PFRULE_RULESRCTRACK ||
-		    r->rpool.opts & PF_POOL_STICKYADDR)
-			k.rule.ptr = r;
-		else
-			k.rule.ptr = NULL;
-		pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
-		*sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
-		if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
-			PF_ACPY(naddr, &(*sn)->raddr, af);
-			if (pf_status.debug >= PF_DEBUG_MISC) {
-				printf("pf_map_addr: src tracking maps ");
-				pf_print_host(&k.addr, 0, af);
-				printf(" to ");
-				pf_print_host(naddr, 0, af);
-				printf("\n");
-			}
-			return (0);
-		}
-	}
+	struct pf_addr		*saddr, *daddr;
+	u_int16_t		 sport, dport;
+#ifdef __FreeBSD__
+	struct inpcbinfo	*pi;
+#else
+	struct inpcbtable	*tb;
+#endif
+	struct inpcb		*inp;
+
+	if (pd == NULL)
+		return (-1);
+	pd->lookup.uid = UID_MAX;
+	pd->lookup.gid = GID_MAX;
+	pd->lookup.pid = NO_PID;
 
-	if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
+#ifdef __FreeBSD__
+	if (inp_arg != NULL) {
+		INP_LOCK_ASSERT(inp_arg);
+		pd->lookup.uid = inp_arg->inp_cred->cr_uid;
+		pd->lookup.gid = inp_arg->inp_cred->cr_groups[0];
 		return (1);
-	if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
-		switch (af) {
-#ifdef INET
-		case AF_INET:
-			if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
-			    (rpool->opts & PF_POOL_TYPEMASK) !=
-			    PF_POOL_ROUNDROBIN)
-				return (1);
-			 raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
-			 rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
-			break;
-#endif /* INET */
-#ifdef INET6
-		case AF_INET6:
-			if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
-			    (rpool->opts & PF_POOL_TYPEMASK) !=
-			    PF_POOL_ROUNDROBIN)
-				return (1);
-			raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
-			rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
-			break;
-#endif /* INET6 */
-		}
-	} else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
-		if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
-			return (1); /* unsupported */
-	} else {
-		raddr = &rpool->cur->addr.v.a.addr;
-		rmask = &rpool->cur->addr.v.a.mask;
 	}
+#endif
 
-	switch (rpool->opts & PF_POOL_TYPEMASK) {
-	case PF_POOL_NONE:
-		PF_ACPY(naddr, raddr, af);
+	switch (pd->proto) {
+	case IPPROTO_TCP:
+		if (pd->hdr.tcp == NULL)
+			return (-1);
+		sport = pd->hdr.tcp->th_sport;
+		dport = pd->hdr.tcp->th_dport;
+#ifdef __FreeBSD__
+		pi = &V_tcbinfo;
+#else
+		tb = &tcbtable;
+#endif
 		break;
-	case PF_POOL_BITMASK:
-		PF_POOLMASK(naddr, raddr, rmask, saddr, af);
+	case IPPROTO_UDP:
+		if (pd->hdr.udp == NULL)
+			return (-1);
+		sport = pd->hdr.udp->uh_sport;
+		dport = pd->hdr.udp->uh_dport;
+#ifdef __FreeBSD__
+		pi = &V_udbinfo;
+#else
+		tb = &udbtable;
+#endif
 		break;
-	case PF_POOL_RANDOM:
-		if (init_addr != NULL && PF_AZERO(init_addr, af)) {
-			switch (af) {
-#ifdef INET
-			case AF_INET:
-				rpool->counter.addr32[0] = htonl(arc4random());
-				break;
-#endif /* INET */
-#ifdef INET6
-			case AF_INET6:
-				if (rmask->addr32[3] != 0xffffffff)
-					rpool->counter.addr32[3] =
-					    htonl(arc4random());
-				else
-					break;
-				if (rmask->addr32[2] != 0xffffffff)
-					rpool->counter.addr32[2] =
-					    htonl(arc4random());
-				else
-					break;
-				if (rmask->addr32[1] != 0xffffffff)
-					rpool->counter.addr32[1] =
-					    htonl(arc4random());
-				else
-					break;
-				if (rmask->addr32[0] != 0xffffffff)
-					rpool->counter.addr32[0] =
-					    htonl(arc4random());
-				break;
-#endif /* INET6 */
-			}
-			PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
-			PF_ACPY(init_addr, naddr, af);
-
-		} else {
-			PF_AINC(&rpool->counter, af);
-			PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
-		}
-		break;
-	case PF_POOL_SRCHASH:
-		pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
-		PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
-		break;
-	case PF_POOL_ROUNDROBIN:
-		if (rpool->cur->addr.type == PF_ADDR_TABLE) {
-			if (!pfr_pool_get(rpool->cur->addr.p.tbl,
-			    &rpool->tblidx, &rpool->counter,
-			    &raddr, &rmask, af))
-				goto get_addr;
-		} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
-			if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
-			    &rpool->tblidx, &rpool->counter,
-			    &raddr, &rmask, af))
-				goto get_addr;
-		} else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
-			goto get_addr;
-
-	try_next:
-		if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL)
-			rpool->cur = TAILQ_FIRST(&rpool->list);
-		if (rpool->cur->addr.type == PF_ADDR_TABLE) {
-			rpool->tblidx = -1;
-			if (pfr_pool_get(rpool->cur->addr.p.tbl,
-			    &rpool->tblidx, &rpool->counter,
-			    &raddr, &rmask, af)) {
-				/* table contains no address of type 'af' */
-				if (rpool->cur != acur)
-					goto try_next;
-				return (1);
-			}
-		} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
-			rpool->tblidx = -1;
-			if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
-			    &rpool->tblidx, &rpool->counter,
-			    &raddr, &rmask, af)) {
-				/* table contains no address of type 'af' */
-				if (rpool->cur != acur)
-					goto try_next;
-				return (1);
-			}
-		} else {
-			raddr = &rpool->cur->addr.v.a.addr;
-			rmask = &rpool->cur->addr.v.a.mask;
-			PF_ACPY(&rpool->counter, raddr, af);
-		}
-
-	get_addr:
-		PF_ACPY(naddr, &rpool->counter, af);
-		if (init_addr != NULL && PF_AZERO(init_addr, af))
-			PF_ACPY(init_addr, naddr, af);
-		PF_AINC(&rpool->counter, af);
-		break;
-	}
-	if (*sn != NULL)
-		PF_ACPY(&(*sn)->raddr, naddr, af);
-
-	if (pf_status.debug >= PF_DEBUG_MISC &&
-	    (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
-		printf("pf_map_addr: selected address ");
-		pf_print_host(naddr, 0, af);
-		printf("\n");
-	}
-
-	return (0);
-}
-
-int
-pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
-    struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
-    struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
-    struct pf_src_node **sn)
-{
-	struct pf_state_cmp	key;
-	struct pf_addr		init_addr;
-	u_int16_t		cut;
-
-	bzero(&init_addr, sizeof(init_addr));
-	if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
-		return (1);
-
-	if (proto == IPPROTO_ICMP) {
-		low = 1;
-		high = 65535;
-	}
-
-	do {
-		key.af = af;
-		key.proto = proto;
-		PF_ACPY(&key.ext.addr, daddr, key.af);
-		PF_ACPY(&key.gwy.addr, naddr, key.af);
-		key.ext.port = dport;
-
-		/*
-		 * port search; start random, step;
-		 * similar 2 portloop in in_pcbbind
-		 */
-		if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
-		    proto == IPPROTO_ICMP)) {
-			key.gwy.port = dport;
-			if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
-				return (0);
-		} else if (low == 0 && high == 0) {
-			key.gwy.port = *nport;
-			if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
-				return (0);
-		} else if (low == high) {
-			key.gwy.port = htons(low);
-			if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) {
-				*nport = htons(low);
-				return (0);
-			}
-		} else {
-			u_int16_t tmp;
-
-			if (low > high) {
-				tmp = low;
-				low = high;
-				high = tmp;
-			}
-			/* low < high */
-			cut = htonl(arc4random()) % (1 + high - low) + low;
-			/* low <= cut <= high */
-			for (tmp = cut; tmp <= high; ++(tmp)) {
-				key.gwy.port = htons(tmp);
-				if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
-				    NULL) {
-					*nport = htons(tmp);
-					return (0);
-				}
-			}
-			for (tmp = cut - 1; tmp >= low; --(tmp)) {
-				key.gwy.port = htons(tmp);
-				if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
-				    NULL) {
-					*nport = htons(tmp);
-					return (0);
-				}
-			}
-		}
-
-		switch (r->rpool.opts & PF_POOL_TYPEMASK) {
-		case PF_POOL_RANDOM:
-		case PF_POOL_ROUNDROBIN:
-			if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
-				return (1);
-			break;
-		case PF_POOL_NONE:
-		case PF_POOL_SRCHASH:
-		case PF_POOL_BITMASK:
-		default:
-			return (1);
-		}
-	} while (! PF_AEQ(&init_addr, naddr, af) );
-
-	return (1);					/* none available */
-}
-
-struct pf_rule *
-pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
-    int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
-    struct pf_addr *daddr, u_int16_t dport, int rs_num)
-{
-	struct pf_rule		*r, *rm = NULL;
-	struct pf_ruleset	*ruleset = NULL;
-	int			 tag = -1;
-	int			 rtableid = -1;
-	int			 asd = 0;
-
-	r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
-	while (r && rm == NULL) {
-		struct pf_rule_addr	*src = NULL, *dst = NULL;
-		struct pf_addr_wrap	*xdst = NULL;
-
-		if (r->action == PF_BINAT && direction == PF_IN) {
-			src = &r->dst;
-			if (r->rpool.cur != NULL)
-				xdst = &r->rpool.cur->addr;
-		} else {
-			src = &r->src;
-			dst = &r->dst;
-		}
-
-		r->evaluations++;
-		if (pfi_kif_match(r->kif, kif) == r->ifnot)
-			r = r->skip[PF_SKIP_IFP].ptr;
-		else if (r->direction && r->direction != direction)
-			r = r->skip[PF_SKIP_DIR].ptr;
-		else if (r->af && r->af != pd->af)
-			r = r->skip[PF_SKIP_AF].ptr;
-		else if (r->proto && r->proto != pd->proto)
-			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
-		    src->neg, kif))
-			r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
-			    PF_SKIP_DST_ADDR].ptr;
-		else if (src->port_op && !pf_match_port(src->port_op,
-		    src->port[0], src->port[1], sport))
-			r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
-			    PF_SKIP_DST_PORT].ptr;
-		else if (dst != NULL &&
-		    PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL))
-			r = r->skip[PF_SKIP_DST_ADDR].ptr;
-		else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
-		    0, NULL))
-			r = TAILQ_NEXT(r, entries);
-		else if (dst != NULL && dst->port_op &&
-		    !pf_match_port(dst->port_op, dst->port[0],
-		    dst->port[1], dport))
-			r = r->skip[PF_SKIP_DST_PORT].ptr;
-		else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
-		    IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
-		    off, pd->hdr.tcp), r->os_fingerprint)))
-			r = TAILQ_NEXT(r, entries);
-		else {
-			if (r->tag)
-				tag = r->tag;
-			if (r->rtableid >= 0)
-				rtableid = r->rtableid;
-			if (r->anchor == NULL) {
-				rm = r;
-			} else
-				pf_step_into_anchor(&asd, &ruleset, rs_num,
-				    &r, NULL, NULL);
-		}
-		if (r == NULL)
-			pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
-			    NULL, NULL);
-	}
-	if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid))
-		return (NULL);
-	if (rm != NULL && (rm->action == PF_NONAT ||
-	    rm->action == PF_NORDR || rm->action == PF_NOBINAT))
-		return (NULL);
-	return (rm);
-}
-
-struct pf_rule *
-pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
-    struct pfi_kif *kif, struct pf_src_node **sn,
-    struct pf_addr *saddr, u_int16_t sport,
-    struct pf_addr *daddr, u_int16_t dport,
-    struct pf_addr *naddr, u_int16_t *nport)
-{
-	struct pf_rule	*r = NULL;
-
-	if (direction == PF_OUT) {
-		r = pf_match_translation(pd, m, off, direction, kif, saddr,
-		    sport, daddr, dport, PF_RULESET_BINAT);
-		if (r == NULL)
-			r = pf_match_translation(pd, m, off, direction, kif,
-			    saddr, sport, daddr, dport, PF_RULESET_NAT);
-	} else {
-		r = pf_match_translation(pd, m, off, direction, kif, saddr,
-		    sport, daddr, dport, PF_RULESET_RDR);
-		if (r == NULL)
-			r = pf_match_translation(pd, m, off, direction, kif,
-			    saddr, sport, daddr, dport, PF_RULESET_BINAT);
-	}
-
-	if (r != NULL) {
-		switch (r->action) {
-		case PF_NONAT:
-		case PF_NOBINAT:
-		case PF_NORDR:
-			return (NULL);
-		case PF_NAT:
-			if (pf_get_sport(pd->af, pd->proto, r, saddr,
-			    daddr, dport, naddr, nport, r->rpool.proxy_port[0],
-			    r->rpool.proxy_port[1], sn)) {
-				DPFPRINTF(PF_DEBUG_MISC,
-				    ("pf: NAT proxy port allocation "
-				    "(%u-%u) failed\n",
-				    r->rpool.proxy_port[0],
-				    r->rpool.proxy_port[1]));
-				return (NULL);
-			}
-			break;
-		case PF_BINAT:
-			switch (direction) {
-			case PF_OUT:
-				if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
-					switch (pd->af) {
-#ifdef INET
-					case AF_INET:
-						if (r->rpool.cur->addr.p.dyn->
-						    pfid_acnt4 < 1)
-							return (NULL);
-						PF_POOLMASK(naddr,
-						    &r->rpool.cur->addr.p.dyn->
-						    pfid_addr4,
-						    &r->rpool.cur->addr.p.dyn->
-						    pfid_mask4,
-						    saddr, AF_INET);
-						break;
-#endif /* INET */
-#ifdef INET6
-					case AF_INET6:
-						if (r->rpool.cur->addr.p.dyn->
-						    pfid_acnt6 < 1)
-							return (NULL);
-						PF_POOLMASK(naddr,
-						    &r->rpool.cur->addr.p.dyn->
-						    pfid_addr6,
-						    &r->rpool.cur->addr.p.dyn->
-						    pfid_mask6,
-						    saddr, AF_INET6);
-						break;
-#endif /* INET6 */
-					}
-				} else
-					PF_POOLMASK(naddr,
-					    &r->rpool.cur->addr.v.a.addr,
-					    &r->rpool.cur->addr.v.a.mask,
-					    saddr, pd->af);
-				break;
-			case PF_IN:
-				if (r->src.addr.type == PF_ADDR_DYNIFTL) {
-					switch (pd->af) {
-#ifdef INET
-					case AF_INET:
-						if (r->src.addr.p.dyn->
-						    pfid_acnt4 < 1)
-							return (NULL);
-						PF_POOLMASK(naddr,
-						    &r->src.addr.p.dyn->
-						    pfid_addr4,
-						    &r->src.addr.p.dyn->
-						    pfid_mask4,
-						    daddr, AF_INET);
-						break;
-#endif /* INET */
-#ifdef INET6
-					case AF_INET6:
-						if (r->src.addr.p.dyn->
-						    pfid_acnt6 < 1)
-							return (NULL);
-						PF_POOLMASK(naddr,
-						    &r->src.addr.p.dyn->
-						    pfid_addr6,
-						    &r->src.addr.p.dyn->
-						    pfid_mask6,
-						    daddr, AF_INET6);
-						break;
-#endif /* INET6 */
-					}
-				} else
-					PF_POOLMASK(naddr,
-					    &r->src.addr.v.a.addr,
-					    &r->src.addr.v.a.mask, daddr,
-					    pd->af);
-				break;
-			}
-			break;
-		case PF_RDR: {
-			if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
-				return (NULL);
-			if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
-			    PF_POOL_BITMASK)
-				PF_POOLMASK(naddr, naddr,
-				    &r->rpool.cur->addr.v.a.mask, daddr,
-				    pd->af);
-
-			if (r->rpool.proxy_port[1]) {
-				u_int32_t	tmp_nport;
-
-				tmp_nport = ((ntohs(dport) -
-				    ntohs(r->dst.port[0])) %
-				    (r->rpool.proxy_port[1] -
-				    r->rpool.proxy_port[0] + 1)) +
-				    r->rpool.proxy_port[0];
-
-				/* wrap around if necessary */
-				if (tmp_nport > 65535)
-					tmp_nport -= 65535;
-				*nport = htons((u_int16_t)tmp_nport);
-			} else if (r->rpool.proxy_port[0])
-				*nport = htons(r->rpool.proxy_port[0]);
-			break;
-		}
-		default:
-			return (NULL);
-		}
-	}
-
-	return (r);
-}
-
-int
-#ifdef __FreeBSD__
-pf_socket_lookup(int direction, struct pf_pdesc *pd, struct inpcb *inp_arg)
-#else
-pf_socket_lookup(int direction, struct pf_pdesc *pd)
-#endif
-{
-	struct pf_addr		*saddr, *daddr;
-	u_int16_t		 sport, dport;
-#ifdef __FreeBSD__
-	struct inpcbinfo	*pi;
-#else
-	struct inpcbtable	*tb;
-#endif
-	struct inpcb		*inp;
-
-	if (pd == NULL)
-		return (-1);
-	pd->lookup.uid = UID_MAX;
-	pd->lookup.gid = GID_MAX;
-	pd->lookup.pid = NO_PID;		/* XXX: revisit */
-#ifdef __FreeBSD__
-	if (inp_arg != NULL) {
-		INP_LOCK_ASSERT(inp_arg);
-		pd->lookup.uid = inp_arg->inp_cred->cr_uid;
-		pd->lookup.gid = inp_arg->inp_cred->cr_groups[0];
-		return (1);
-	}
-#endif
-	switch (pd->proto) {
-	case IPPROTO_TCP:
-		if (pd->hdr.tcp == NULL)
-			return (-1);
-		sport = pd->hdr.tcp->th_sport;
-		dport = pd->hdr.tcp->th_dport;
-#ifdef __FreeBSD__
-		pi = &V_tcbinfo;
-#else
-		tb = &tcbtable;
-#endif
-		break;
-	case IPPROTO_UDP:
-		if (pd->hdr.udp == NULL)
-			return (-1);
-		sport = pd->hdr.udp->uh_sport;
-		dport = pd->hdr.udp->uh_dport;
-#ifdef __FreeBSD__
-		pi = &V_udbinfo;
-#else
-		tb = &udbtable;
-#endif
-		break;
-	default:
-		return (-1);
-	}
-	if (direction == PF_IN) {
-		saddr = pd->src;
-		daddr = pd->dst;
-	} else {
-		u_int16_t	p;
+	default:
+		return (-1);
+	}
+	if (direction == PF_IN) {
+		saddr = pd->src;
+		daddr = pd->dst;
+	} else {
+		u_int16_t	p;
 
 		p = sport;
 		sport = dport;
@@ -3050,7 +3017,8 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
 #else
 		inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
 		if (inp == NULL) {
-			inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
+			inp = in_pcblookup_listen(tb, daddr->v4, dport, 0,
+			    NULL);
 			if (inp == NULL)
 				return (-1);
 		}
@@ -3077,7 +3045,8 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
 		inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
 		    dport);
 		if (inp == NULL) {
-			inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0);
+			inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0,
+			    NULL);
 			if (inp == NULL)
 				return (-1);
 		}
@@ -3147,7 +3116,11 @@ pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
 	int		 hlen;
 	u_int8_t	 hdr[60];
 	u_int8_t	*opt, optlen;
+#ifdef __FreeBSD__
 	u_int16_t	 mss = V_tcp_mssdflt;
+#else
+	u_int16_t	 mss = tcp_mssdflt;
+#endif
 
 	hlen = th_off << 2;	/* hlen <= sizeof(hdr) */
 	if (hlen <= sizeof(struct tcphdr))
@@ -3191,8 +3164,13 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
 	struct route_in6	 ro6;
 #endif /* INET6 */
 	struct rtentry		*rt = NULL;
-	int			 hlen = 0;	/* make the compiler happy */
+#ifdef __FreeBSD__
+	int			 hlen = 0;
 	u_int16_t		 mss = V_tcp_mssdflt;
+#else
+	int			 hlen;
+	u_int16_t		 mss = tcp_mssdflt;
+#endif
 
 	switch (af) {
 #ifdef INET
@@ -3240,7 +3218,11 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
 
 	if (rt && rt->rt_ifp) {
 		mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
+#ifdef __FreeBSD__
 		mss = max(V_tcp_mssdflt, mss);
+#else
+		mss = max(tcp_mssdflt, mss);
+#endif
 		RTFREE(rt);
 	}
 	mss = min(mss, offer);
@@ -3252,55 +3234,113 @@ void
 pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
 {
 	struct pf_rule *r = s->rule.ptr;
+	struct pf_src_node *sn = NULL;
 
 	s->rt_kif = NULL;
 	if (!r->rt || r->rt == PF_FASTROUTE)
 		return;
-	switch (s->af) {
+	switch (s->key[PF_SK_WIRE]->af) {
 #ifdef INET
 	case AF_INET:
-		pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL,
-		    &s->nat_src_node);
+		pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &sn);
 		s->rt_kif = r->rpool.cur->kif;
 		break;
 #endif /* INET */
 #ifdef INET6
 	case AF_INET6:
-		pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL,
-		    &s->nat_src_node);
+		pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &sn);
 		s->rt_kif = r->rpool.cur->kif;
 		break;
 #endif /* INET6 */
 	}
 }
 
+u_int32_t
+pf_tcp_iss(struct pf_pdesc *pd)
+{
+	MD5_CTX ctx;
+	u_int32_t digest[4];
+
+#ifdef __FreeBSD__
+	if (V_pf_tcp_secret_init == 0) {
+		read_random(&V_pf_tcp_secret, sizeof(V_pf_tcp_secret));
+		MD5Init(&V_pf_tcp_secret_ctx);
+		MD5Update(&V_pf_tcp_secret_ctx, V_pf_tcp_secret,
+		    sizeof(V_pf_tcp_secret));
+		V_pf_tcp_secret_init = 1;
+	}
+
+	ctx = V_pf_tcp_secret_ctx;
+#else
+	if (pf_tcp_secret_init == 0) {
+		arc4random_buf(pf_tcp_secret, sizeof(pf_tcp_secret));
+		MD5Init(&pf_tcp_secret_ctx);
+		MD5Update(&pf_tcp_secret_ctx, pf_tcp_secret,
+		    sizeof(pf_tcp_secret));
+		pf_tcp_secret_init = 1;
+	}
+
+	ctx = pf_tcp_secret_ctx;
+#endif
+
+	MD5Update(&ctx, (char *)&pd->hdr.tcp->th_sport, sizeof(u_short));
+	MD5Update(&ctx, (char *)&pd->hdr.tcp->th_dport, sizeof(u_short));
+	if (pd->af == AF_INET6) {
+		MD5Update(&ctx, (char *)&pd->src->v6, sizeof(struct in6_addr));
+		MD5Update(&ctx, (char *)&pd->dst->v6, sizeof(struct in6_addr));
+	} else {
+		MD5Update(&ctx, (char *)&pd->src->v4, sizeof(struct in_addr));
+		MD5Update(&ctx, (char *)&pd->dst->v4, sizeof(struct in_addr));
+	}
+	MD5Final((u_char *)digest, &ctx);
+#ifdef __FreeBSD__
+	V_pf_tcp_iss_off += 4096;
+#define	ISN_RANDOM_INCREMENT (4096 - 1)
+	return (digest[0] + (arc4random() & ISN_RANDOM_INCREMENT) +
+	    V_pf_tcp_iss_off);
+#undef	ISN_RANDOM_INCREMENT
+#else
+	pf_tcp_iss_off += 4096;
+	return (digest[0] + tcp_iss + pf_tcp_iss_off);
+#endif
+}
+
 int
-pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
+pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction,
     struct pfi_kif *kif, struct mbuf *m, int off, void *h,
-#ifdef __FreeBSD__
     struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+#ifdef __FreeBSD__
     struct ifqueue *ifq, struct inpcb *inp)
 #else
-    struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
     struct ifqueue *ifq)
 #endif
 {
 	struct pf_rule		*nr = NULL;
 	struct pf_addr		*saddr = pd->src, *daddr = pd->dst;
-	struct tcphdr		*th = pd->hdr.tcp;
-	u_int16_t		 bport, nport = 0;
 	sa_family_t		 af = pd->af;
 	struct pf_rule		*r, *a = NULL;
 	struct pf_ruleset	*ruleset = NULL;
 	struct pf_src_node	*nsn = NULL;
+	struct tcphdr		*th = pd->hdr.tcp;
+	struct pf_state_key	*skw = NULL, *sks = NULL;
+	struct pf_state_key	*sk = NULL, *nk = NULL;
 	u_short			 reason;
-	int			 rewrite = 0;
+	int			 rewrite = 0, hdrlen = 0;
 	int			 tag = -1, rtableid = -1;
-	u_int16_t		 mss = V_tcp_mssdflt;
 	int			 asd = 0;
 	int			 match = 0;
+	int			 state_icmp = 0;
+#ifdef __FreeBSD__
+	u_int16_t		 sport = 0, dport = 0;
+	u_int16_t		 bproto_sum = 0, bip_sum = 0;
+#else
+	u_int16_t		 sport, dport;
+	u_int16_t		 bproto_sum = 0, bip_sum;
+#endif
+	u_int8_t		 icmptype = 0, icmpcode = 0;
+
 
-	if (pf_check_congestion(ifq)) {
+	if (direction == PF_IN && pf_check_congestion(ifq)) {
 		REASON_SET(&reason, PFRES_CONGEST);
 		return (PF_DROP);
 	}
@@ -3308,746 +3348,33 @@ pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
 #ifdef __FreeBSD__
 	if (inp != NULL)
 		pd->lookup.done = pf_socket_lookup(direction, pd, inp);
-	else if (debug_pfugidhack) {
+	else if (V_debug_pfugidhack) {
 		PF_UNLOCK();
 		DPFPRINTF(PF_DEBUG_MISC, ("pf: unlocked lookup\n"));
-		pd->lookup.done = pf_socket_lookup(direction, pd, inp);
+		    pd->lookup.done = pf_socket_lookup(direction, pd, inp);
 		PF_LOCK();
 	}
 #endif
 
-	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
-
-	if (direction == PF_OUT) {
-		bport = nport = th->th_sport;
-		/* check outgoing packet for BINAT/NAT */
-		if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
-		    saddr, th->th_sport, daddr, th->th_dport,
-		    &pd->naddr, &nport)) != NULL) {
-			PF_ACPY(&pd->baddr, saddr, af);
-			pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
-			    &th->th_sum, &pd->naddr, nport, 0, af);
-			rewrite++;
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
-		}
-	} else {
-		bport = nport = th->th_dport;
-		/* check incoming packet for BINAT/RDR */
-		if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
-		    saddr, th->th_sport, daddr, th->th_dport,
-		    &pd->naddr, &nport)) != NULL) {
-			PF_ACPY(&pd->baddr, daddr, af);
-			pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
-			    &th->th_sum, &pd->naddr, nport, 0, af);
-			rewrite++;
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
-		}
-	}
-
-	while (r != NULL) {
-		r->evaluations++;
-		if (pfi_kif_match(r->kif, kif) == r->ifnot)
-			r = r->skip[PF_SKIP_IFP].ptr;
-		else if (r->direction && r->direction != direction)
-			r = r->skip[PF_SKIP_DIR].ptr;
-		else if (r->af && r->af != af)
-			r = r->skip[PF_SKIP_AF].ptr;
-		else if (r->proto && r->proto != IPPROTO_TCP)
-			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
-		    r->src.neg, kif))
-			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
-		else if (r->src.port_op && !pf_match_port(r->src.port_op,
-		    r->src.port[0], r->src.port[1], th->th_sport))
-			r = r->skip[PF_SKIP_SRC_PORT].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
-		    r->dst.neg, NULL))
-			r = r->skip[PF_SKIP_DST_ADDR].ptr;
-		else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
-		    r->dst.port[0], r->dst.port[1], th->th_dport))
-			r = r->skip[PF_SKIP_DST_PORT].ptr;
-		else if (r->tos && !(r->tos == pd->tos))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->rule_flag & PFRULE_FRAGMENT)
-			r = TAILQ_NEXT(r, entries);
-		else if ((r->flagset & th->th_flags) != r->flags)
-			r = TAILQ_NEXT(r, entries);
-		else if (r->uid.op && (pd->lookup.done || (pd->lookup.done =
-#ifdef __FreeBSD__
-		    pf_socket_lookup(direction, pd, inp), 1)) &&
-#else
-		    pf_socket_lookup(direction, pd), 1)) &&
-#endif
-		    !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
-		    pd->lookup.uid))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->gid.op && (pd->lookup.done || (pd->lookup.done =
-#ifdef __FreeBSD__
-		    pf_socket_lookup(direction, pd, inp), 1)) &&
-#else
-		    pf_socket_lookup(direction, pd), 1)) &&
-#endif
-		    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
-		    pd->lookup.gid))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->prob && r->prob <= arc4random())
-			r = TAILQ_NEXT(r, entries);
-		else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
-		    pf_osfp_fingerprint(pd, m, off, th), r->os_fingerprint))
-			r = TAILQ_NEXT(r, entries);
-		else {
-			if (r->tag)
-				tag = r->tag;
-			if (r->rtableid >= 0)
-				rtableid = r->rtableid;
-			if (r->anchor == NULL) {
-				match = 1;
-				*rm = r;
-				*am = a;
-				*rsm = ruleset;
-				if ((*rm)->quick)
-					break;
-				r = TAILQ_NEXT(r, entries);
-			} else
-				pf_step_into_anchor(&asd, &ruleset,
-				    PF_RULESET_FILTER, &r, &a, &match);
-		}
-		if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
-		    PF_RULESET_FILTER, &r, &a, &match))
-			break;
-	}
-	r = *rm;
-	a = *am;
-	ruleset = *rsm;
-
-	REASON_SET(&reason, PFRES_MATCH);
-
-	if (r->log || (nr != NULL && nr->natpass && nr->log)) {
-		if (rewrite)
-#ifdef __FreeBSD__
-			m_copyback(m, off, sizeof(*th), (caddr_t)th);
-#else
-			m_copyback(m, off, sizeof(*th), th);
-#endif
-		PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
-		    a, ruleset, pd);
-	}
-
-	if ((r->action == PF_DROP) &&
-	    ((r->rule_flag & PFRULE_RETURNRST) ||
-	    (r->rule_flag & PFRULE_RETURNICMP) ||
-	    (r->rule_flag & PFRULE_RETURN))) {
-		/* undo NAT changes, if they have taken place */
-		if (nr != NULL) {
-			if (direction == PF_OUT) {
-				pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
-				    &th->th_sum, &pd->baddr, bport, 0, af);
-				rewrite++;
-			} else {
-				pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
-				    &th->th_sum, &pd->baddr, bport, 0, af);
-				rewrite++;
-			}
-		}
-		if (((r->rule_flag & PFRULE_RETURNRST) ||
-		    (r->rule_flag & PFRULE_RETURN)) &&
-		    !(th->th_flags & TH_RST)) {
-			u_int32_t ack = ntohl(th->th_seq) + pd->p_len;
-
-			if (th->th_flags & TH_SYN)
-				ack++;
-			if (th->th_flags & TH_FIN)
-				ack++;
-#ifdef __FreeBSD__
-			pf_send_tcp(m, r, af, pd->dst,
-#else
-			pf_send_tcp(r, af, pd->dst,
-#endif
-			    pd->src, th->th_dport, th->th_sport,
-			    ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
-			    r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
-		} else if ((af == AF_INET) && r->return_icmp)
-			pf_send_icmp(m, r->return_icmp >> 8,
-			    r->return_icmp & 255, af, r);
-		else if ((af == AF_INET6) && r->return_icmp6)
-			pf_send_icmp(m, r->return_icmp6 >> 8,
-			    r->return_icmp6 & 255, af, r);
-	}
-
-	if (r->action == PF_DROP)
-		return (PF_DROP);
-
-	if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
-		REASON_SET(&reason, PFRES_MEMORY);
-		return (PF_DROP);
-	}
-
-	if (r->keep_state || nr != NULL ||
-	    (pd->flags & PFDESC_TCP_NORM)) {
-		/* create new state */
-		u_int16_t	 len;
-		struct pf_state	*s = NULL;
-		struct pf_src_node *sn = NULL;
-
-		len = pd->tot_len - off - (th->th_off << 2);
-
-		/* check maximums */
-		if (r->max_states && (r->states >= r->max_states)) {
-			pf_status.lcounters[LCNT_STATES]++;
-			REASON_SET(&reason, PFRES_MAXSTATES);
-			goto cleanup;
-		}
-		/* src node for filter rule */
-		if ((r->rule_flag & PFRULE_SRCTRACK ||
-		    r->rpool.opts & PF_POOL_STICKYADDR) &&
-		    pf_insert_src_node(&sn, r, saddr, af) != 0) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		/* src node for translation rule */
-		if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
-		    ((direction == PF_OUT &&
-		    pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
-		    (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		s = pool_get(&pf_state_pl, PR_NOWAIT);
-		if (s == NULL) {
-			REASON_SET(&reason, PFRES_MEMORY);
-cleanup:
-			if (sn != NULL && sn->states == 0 && sn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, sn);
-			}
-			if (nsn != sn && nsn != NULL && nsn->states == 0 &&
-			    nsn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, nsn);
-			}
-			return (PF_DROP);
-		}
-		bzero(s, sizeof(*s));
-		s->rule.ptr = r;
-		s->nat_rule.ptr = nr;
-		s->anchor.ptr = a;
-		STATE_INC_COUNTERS(s);
-		if (r->allow_opts)
-			s->state_flags |= PFSTATE_ALLOWOPTS;
-		if (r->rule_flag & PFRULE_STATESLOPPY)
-			s->state_flags |= PFSTATE_SLOPPY;
-		s->log = r->log & PF_LOG_ALL;
-		if (nr != NULL)
-			s->log |= nr->log & PF_LOG_ALL;
-		s->proto = IPPROTO_TCP;
-		s->direction = direction;
-		s->af = af;
-		if (direction == PF_OUT) {
-			PF_ACPY(&s->gwy.addr, saddr, af);
-			s->gwy.port = th->th_sport;		/* sport */
-			PF_ACPY(&s->ext.addr, daddr, af);
-			s->ext.port = th->th_dport;
-			if (nr != NULL) {
-				PF_ACPY(&s->lan.addr, &pd->baddr, af);
-				s->lan.port = bport;
-			} else {
-				PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
-				s->lan.port = s->gwy.port;
-			}
-		} else {
-			PF_ACPY(&s->lan.addr, daddr, af);
-			s->lan.port = th->th_dport;
-			PF_ACPY(&s->ext.addr, saddr, af);
-			s->ext.port = th->th_sport;
-			if (nr != NULL) {
-				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
-				s->gwy.port = bport;
-			} else {
-				PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
-				s->gwy.port = s->lan.port;
-			}
-		}
-
-		s->src.seqlo = ntohl(th->th_seq);
-		s->src.seqhi = s->src.seqlo + len + 1;
-		if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
-		    r->keep_state == PF_STATE_MODULATE) {
-			/* Generate sequence number modulator */
-#ifdef __FreeBSD__
-			while ((s->src.seqdiff =
-			    pf_new_isn(s) - s->src.seqlo) == 0)
-				;	
-#else
-			while ((s->src.seqdiff =
-			    tcp_rndiss_next() - s->src.seqlo) == 0)
-				;
-#endif
-			pf_change_a(&th->th_seq, &th->th_sum,
-			    htonl(s->src.seqlo + s->src.seqdiff), 0);
-			rewrite = 1;
-		} else
-			s->src.seqdiff = 0;
-		if (th->th_flags & TH_SYN) {
-			s->src.seqhi++;
-			s->src.wscale = pf_get_wscale(m, off, th->th_off, af);
-		}
-		s->src.max_win = MAX(ntohs(th->th_win), 1);
-		if (s->src.wscale & PF_WSCALE_MASK) {
-			/* Remove scale factor from initial window */
-			int win = s->src.max_win;
-			win += 1 << (s->src.wscale & PF_WSCALE_MASK);
-			s->src.max_win = (win - 1) >>
-			    (s->src.wscale & PF_WSCALE_MASK);
-		}
-		if (th->th_flags & TH_FIN)
-			s->src.seqhi++;
-		s->dst.seqhi = 1;
-		s->dst.max_win = 1;
-		s->src.state = TCPS_SYN_SENT;
-		s->dst.state = TCPS_CLOSED;
-		s->creation = time_second;
-		s->expire = time_second;
-		s->timeout = PFTM_TCP_FIRST_PACKET;
-		pf_set_rt_ifp(s, saddr);
-		if (sn != NULL) {
-			s->src_node = sn;
-			s->src_node->states++;
-		}
-		if (nsn != NULL) {
-			PF_ACPY(&nsn->raddr, &pd->naddr, af);
-			s->nat_src_node = nsn;
-			s->nat_src_node->states++;
-		}
-		if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
-		    off, pd, th, &s->src, &s->dst)) {
-			REASON_SET(&reason, PFRES_MEMORY);
-			pf_src_tree_remove_state(s);
-			STATE_DEC_COUNTERS(s);
-			pool_put(&pf_state_pl, s);
-			return (PF_DROP);
-		}
-		if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
-		    pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
-		    &s->src, &s->dst, &rewrite)) {
-			/* This really shouldn't happen!!! */
-			DPFPRINTF(PF_DEBUG_URGENT,
-			    ("pf_normalize_tcp_stateful failed on first pkt"));
-			pf_normalize_tcp_cleanup(s);
-			pf_src_tree_remove_state(s);
-			STATE_DEC_COUNTERS(s);
-			pool_put(&pf_state_pl, s);
-			return (PF_DROP);
-		}
-		if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
-			pf_normalize_tcp_cleanup(s);
-			REASON_SET(&reason, PFRES_STATEINS);
-			pf_src_tree_remove_state(s);
-			STATE_DEC_COUNTERS(s);
-			pool_put(&pf_state_pl, s);
-			return (PF_DROP);
-		} else
-			*sm = s;
-		if (tag > 0) {
-			pf_tag_ref(tag);
-			s->tag = tag;
-		}
-		if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
-		    r->keep_state == PF_STATE_SYNPROXY) {
-			s->src.state = PF_TCPS_PROXY_SRC;
-			if (nr != NULL) {
-				if (direction == PF_OUT) {
-					pf_change_ap(saddr, &th->th_sport,
-					    pd->ip_sum, &th->th_sum, &pd->baddr,
-					    bport, 0, af);
-				} else {
-					pf_change_ap(daddr, &th->th_dport,
-					    pd->ip_sum, &th->th_sum, &pd->baddr,
-					    bport, 0, af);
-				}
-			}
-			s->src.seqhi = htonl(arc4random());
-			/* Find mss option */
-			mss = pf_get_mss(m, off, th->th_off, af);
-			mss = pf_calc_mss(saddr, af, mss);
-			mss = pf_calc_mss(daddr, af, mss);
-			s->src.mss = mss;
-#ifdef __FreeBSD__
-			pf_send_tcp(NULL, r, af, daddr, saddr, th->th_dport,
-#else
-			pf_send_tcp(r, af, daddr, saddr, th->th_dport,
-#endif
-			    th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
-			    TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
-			REASON_SET(&reason, PFRES_SYNPROXY);
-			return (PF_SYNPROXY_DROP);
-		}
-	}
-
-	/* copy back packet headers if we performed NAT operations */
-	if (rewrite)
-		m_copyback(m, off, sizeof(*th), (caddr_t)th);
-
-	return (PF_PASS);
-}
-
-int
-pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
-    struct pfi_kif *kif, struct mbuf *m, int off, void *h,
-#ifdef __FreeBSD__
-    struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
-    struct ifqueue *ifq, struct inpcb *inp)
-#else
-    struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
-    struct ifqueue *ifq)
-#endif
-{
-	struct pf_rule		*nr = NULL;
-	struct pf_addr		*saddr = pd->src, *daddr = pd->dst;
-	struct udphdr		*uh = pd->hdr.udp;
-	u_int16_t		 bport, nport = 0;
-	sa_family_t		 af = pd->af;
-	struct pf_rule		*r, *a = NULL;
-	struct pf_ruleset	*ruleset = NULL;
-	struct pf_src_node	*nsn = NULL;
-	u_short			 reason;
-	int			 rewrite = 0;
-	int			 tag = -1, rtableid = -1;
-	int			 asd = 0;
-	int			 match = 0;
-
-	if (pf_check_congestion(ifq)) {
-		REASON_SET(&reason, PFRES_CONGEST);
-		return (PF_DROP);
-	}
-
-#ifdef __FreeBSD__
-	if (inp != NULL)
-		pd->lookup.done = pf_socket_lookup(direction, pd, inp);
-	else if (debug_pfugidhack) {
-		PF_UNLOCK();
-		DPFPRINTF(PF_DEBUG_MISC, ("pf: unlocked lookup\n"));
-		pd->lookup.done = pf_socket_lookup(direction, pd, inp);
-		PF_LOCK();
-	}
-#endif
-
-	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
-
-	if (direction == PF_OUT) {
-		bport = nport = uh->uh_sport;
-		/* check outgoing packet for BINAT/NAT */
-		if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
-		    saddr, uh->uh_sport, daddr, uh->uh_dport,
-		    &pd->naddr, &nport)) != NULL) {
-			PF_ACPY(&pd->baddr, saddr, af);
-			pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
-			    &uh->uh_sum, &pd->naddr, nport, 1, af);
-			rewrite++;
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
-		}
-	} else {
-		bport = nport = uh->uh_dport;
-		/* check incoming packet for BINAT/RDR */
-		if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
-		    saddr, uh->uh_sport, daddr, uh->uh_dport, &pd->naddr,
-		    &nport)) != NULL) {
-			PF_ACPY(&pd->baddr, daddr, af);
-			pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
-			    &uh->uh_sum, &pd->naddr, nport, 1, af);
-			rewrite++;
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
-		}
-	}
-
-	while (r != NULL) {
-		r->evaluations++;
-		if (pfi_kif_match(r->kif, kif) == r->ifnot)
-			r = r->skip[PF_SKIP_IFP].ptr;
-		else if (r->direction && r->direction != direction)
-			r = r->skip[PF_SKIP_DIR].ptr;
-		else if (r->af && r->af != af)
-			r = r->skip[PF_SKIP_AF].ptr;
-		else if (r->proto && r->proto != IPPROTO_UDP)
-			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
-		    r->src.neg, kif))
-			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
-		else if (r->src.port_op && !pf_match_port(r->src.port_op,
-		    r->src.port[0], r->src.port[1], uh->uh_sport))
-			r = r->skip[PF_SKIP_SRC_PORT].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
-		    r->dst.neg, NULL))
-			r = r->skip[PF_SKIP_DST_ADDR].ptr;
-		else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
-		    r->dst.port[0], r->dst.port[1], uh->uh_dport))
-			r = r->skip[PF_SKIP_DST_PORT].ptr;
-		else if (r->tos && !(r->tos == pd->tos))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->rule_flag & PFRULE_FRAGMENT)
-			r = TAILQ_NEXT(r, entries);
-		else if (r->uid.op && (pd->lookup.done || (pd->lookup.done =
-#ifdef __FreeBSD__
-		    pf_socket_lookup(direction, pd, inp), 1)) &&
-#else
-		    pf_socket_lookup(direction, pd), 1)) &&
-#endif
-		    !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
-		    pd->lookup.uid))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->gid.op && (pd->lookup.done || (pd->lookup.done =
-#ifdef __FreeBSD__
-		    pf_socket_lookup(direction, pd, inp), 1)) &&
-#else
-		    pf_socket_lookup(direction, pd), 1)) &&
-#endif
-		    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
-		    pd->lookup.gid))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->prob && r->prob <= arc4random())
-			r = TAILQ_NEXT(r, entries);
-		else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->os_fingerprint != PF_OSFP_ANY)
-			r = TAILQ_NEXT(r, entries);
-		else {
-			if (r->tag)
-				tag = r->tag;
-			if (r->rtableid >= 0)
-				rtableid = r->rtableid;
-			if (r->anchor == NULL) {
-				match = 1;
-				*rm = r;
-				*am = a;
-				*rsm = ruleset;
-				if ((*rm)->quick)
-					break;
-				r = TAILQ_NEXT(r, entries);
-			} else
-				pf_step_into_anchor(&asd, &ruleset,
-				    PF_RULESET_FILTER, &r, &a, &match);
-		}
-		if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
-		    PF_RULESET_FILTER, &r, &a, &match))
-			break;
-	}
-	r = *rm;
-	a = *am;
-	ruleset = *rsm;
-
-	REASON_SET(&reason, PFRES_MATCH);
-
-	if (r->log || (nr != NULL && nr->natpass && nr->log)) {
-		if (rewrite)
-#ifdef __FreeBSD__
-			m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
-#else
-			m_copyback(m, off, sizeof(*uh), uh);
-#endif
-		PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
-		    a, ruleset, pd);
-	}
-
-	if ((r->action == PF_DROP) &&
-	    ((r->rule_flag & PFRULE_RETURNICMP) ||
-	    (r->rule_flag & PFRULE_RETURN))) {
-		/* undo NAT changes, if they have taken place */
-		if (nr != NULL) {
-			if (direction == PF_OUT) {
-				pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
-				    &uh->uh_sum, &pd->baddr, bport, 1, af);
-				rewrite++;
-			} else {
-				pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
-				    &uh->uh_sum, &pd->baddr, bport, 1, af);
-				rewrite++;
-			}
-		}
-		if ((af == AF_INET) && r->return_icmp)
-			pf_send_icmp(m, r->return_icmp >> 8,
-			    r->return_icmp & 255, af, r);
-		else if ((af == AF_INET6) && r->return_icmp6)
-			pf_send_icmp(m, r->return_icmp6 >> 8,
-			    r->return_icmp6 & 255, af, r);
-	}
-
-	if (r->action == PF_DROP)
-		return (PF_DROP);
-
-	if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
-		REASON_SET(&reason, PFRES_MEMORY);
-		return (PF_DROP);
-	}
-
-	if (r->keep_state || nr != NULL) {
-		/* create new state */
-		struct pf_state	*s = NULL;
-		struct pf_src_node *sn = NULL;
-
-		/* check maximums */
-		if (r->max_states && (r->states >= r->max_states)) {
-			pf_status.lcounters[LCNT_STATES]++;
-			REASON_SET(&reason, PFRES_MAXSTATES);
-			goto cleanup;
-		}
-		/* src node for filter rule */
-		if ((r->rule_flag & PFRULE_SRCTRACK ||
-		    r->rpool.opts & PF_POOL_STICKYADDR) &&
-		    pf_insert_src_node(&sn, r, saddr, af) != 0) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		/* src node for translation rule */
-		if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
-		    ((direction == PF_OUT &&
-		    pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
-		    (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		s = pool_get(&pf_state_pl, PR_NOWAIT);
-		if (s == NULL) {
-			REASON_SET(&reason, PFRES_MEMORY);
-cleanup:
-			if (sn != NULL && sn->states == 0 && sn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, sn);
-			}
-			if (nsn != sn && nsn != NULL && nsn->states == 0 &&
-			    nsn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, nsn);
-			}
-			return (PF_DROP);
-		}
-		bzero(s, sizeof(*s));
-		s->rule.ptr = r;
-		s->nat_rule.ptr = nr;
-		s->anchor.ptr = a;
-		STATE_INC_COUNTERS(s);
-		if (r->allow_opts)
-			s->state_flags |= PFSTATE_ALLOWOPTS;
- 		if (r->rule_flag & PFRULE_STATESLOPPY)
-			s->state_flags |= PFSTATE_SLOPPY;
-		s->log = r->log & PF_LOG_ALL;
-		if (nr != NULL)
-			s->log |= nr->log & PF_LOG_ALL;
-		s->proto = IPPROTO_UDP;
-		s->direction = direction;
-		s->af = af;
-		if (direction == PF_OUT) {
-			PF_ACPY(&s->gwy.addr, saddr, af);
-			s->gwy.port = uh->uh_sport;
-			PF_ACPY(&s->ext.addr, daddr, af);
-			s->ext.port = uh->uh_dport;
-			if (nr != NULL) {
-				PF_ACPY(&s->lan.addr, &pd->baddr, af);
-				s->lan.port = bport;
-			} else {
-				PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
-				s->lan.port = s->gwy.port;
-			}
-		} else {
-			PF_ACPY(&s->lan.addr, daddr, af);
-			s->lan.port = uh->uh_dport;
-			PF_ACPY(&s->ext.addr, saddr, af);
-			s->ext.port = uh->uh_sport;
-			if (nr != NULL) {
-				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
-				s->gwy.port = bport;
-			} else {
-				PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
-				s->gwy.port = s->lan.port;
-			}
-		}
-		s->src.state = PFUDPS_SINGLE;
-		s->dst.state = PFUDPS_NO_TRAFFIC;
-		s->creation = time_second;
-		s->expire = time_second;
-		s->timeout = PFTM_UDP_FIRST_PACKET;
-		pf_set_rt_ifp(s, saddr);
-		if (sn != NULL) {
-			s->src_node = sn;
-			s->src_node->states++;
-		}
-		if (nsn != NULL) {
-			PF_ACPY(&nsn->raddr, &pd->naddr, af);
-			s->nat_src_node = nsn;
-			s->nat_src_node->states++;
-		}
-		if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
-			REASON_SET(&reason, PFRES_STATEINS);
-			pf_src_tree_remove_state(s);
-			STATE_DEC_COUNTERS(s);
-			pool_put(&pf_state_pl, s);
-			return (PF_DROP);
-		} else
-			*sm = s;
-		if (tag > 0) {
-			pf_tag_ref(tag);
-			s->tag = tag;
-		}
-	}
-
-	/* copy back packet headers if we performed NAT operations */
-	if (rewrite)
-		m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
-
-	return (PF_PASS);
-}
-
-int
-pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
-    struct pfi_kif *kif, struct mbuf *m, int off, void *h,
-    struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
-    struct ifqueue *ifq)
-{
-	struct pf_rule		*nr = NULL;
-	struct pf_addr		*saddr = pd->src, *daddr = pd->dst;
-	struct pf_rule		*r, *a = NULL;
-	struct pf_ruleset	*ruleset = NULL;
-	struct pf_src_node	*nsn = NULL;
-	u_short			 reason;
-	u_int16_t		 icmpid = 0, bport, nport = 0;
-	sa_family_t		 af = pd->af;
-	u_int8_t		 icmptype = 0;	/* make the compiler happy */
-	u_int8_t		 icmpcode = 0;	/* make the compiler happy */
-	int			 state_icmp = 0;
-	int			 tag = -1, rtableid = -1;
-#ifdef INET6
-	int			 rewrite = 0;
-#endif /* INET6 */
-	int			 asd = 0;
-	int			 match = 0;
-
-	if (pf_check_congestion(ifq)) {
-		REASON_SET(&reason, PFRES_CONGEST);
-		return (PF_DROP);
-	}
-
 	switch (pd->proto) {
+	case IPPROTO_TCP:
+		sport = th->th_sport;
+		dport = th->th_dport;
+		hdrlen = sizeof(*th);
+		break;
+	case IPPROTO_UDP:
+		sport = pd->hdr.udp->uh_sport;
+		dport = pd->hdr.udp->uh_dport;
+		hdrlen = sizeof(*pd->hdr.udp);
+		break;
 #ifdef INET
 	case IPPROTO_ICMP:
+		if (pd->af != AF_INET)
+			break;
+		sport = dport = pd->hdr.icmp->icmp_id;
+		hdrlen = sizeof(*pd->hdr.icmp);
 		icmptype = pd->hdr.icmp->icmp_type;
 		icmpcode = pd->hdr.icmp->icmp_code;
-		icmpid = pd->hdr.icmp->icmp_id;
 
 		if (icmptype == ICMP_UNREACH ||
 		    icmptype == ICMP_SOURCEQUENCH ||
@@ -4059,9 +3386,12 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
 #endif /* INET */
 #ifdef INET6
 	case IPPROTO_ICMPV6:
+		if (af != AF_INET6)
+			break;
+		sport = dport = pd->hdr.icmp6->icmp6_id;
+		hdrlen = sizeof(*pd->hdr.icmp6);
 		icmptype = pd->hdr.icmp6->icmp6_type;
 		icmpcode = pd->hdr.icmp6->icmp6_code;
-		icmpid = pd->hdr.icmp6->icmp6_id;
 
 		if (icmptype == ICMP6_DST_UNREACH ||
 		    icmptype == ICMP6_PACKET_TOO_BIG ||
@@ -4070,67 +3400,141 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
 			state_icmp++;
 		break;
 #endif /* INET6 */
+	default:
+		sport = dport = hdrlen = 0;
+		break;
 	}
 
 	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
 
-	if (direction == PF_OUT) {
-		bport = nport = icmpid;
-		/* check outgoing packet for BINAT/NAT */
-		if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
-		    saddr, icmpid, daddr, icmpid, &pd->naddr, &nport)) !=
-		    NULL) {
-			PF_ACPY(&pd->baddr, saddr, af);
-			switch (af) {
+	/* check packet for BINAT/NAT/RDR */
+	if ((nr = pf_get_translation(pd, m, off, direction, kif, &nsn,
+	    &skw, &sks, &sk, &nk, saddr, daddr, sport, dport)) != NULL) {
+		if (nk == NULL || sk == NULL) {
+			REASON_SET(&reason, PFRES_MEMORY);
+			goto cleanup;
+		}
+
+		if (pd->ip_sum)
+			bip_sum = *pd->ip_sum;
+
+		switch (pd->proto) {
+		case IPPROTO_TCP:
+			bproto_sum = th->th_sum;
+			pd->proto_sum = &th->th_sum;
+
+			if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
+			    nk->port[pd->sidx] != sport) {
+				pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
+				    &th->th_sum, &nk->addr[pd->sidx],
+				    nk->port[pd->sidx], 0, af);
+				pd->sport = &th->th_sport;
+				sport = th->th_sport;
+			}
+
+			if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
+			    nk->port[pd->didx] != dport) {
+				pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
+				    &th->th_sum, &nk->addr[pd->didx],
+				    nk->port[pd->didx], 0, af);
+				dport = th->th_dport;
+				pd->dport = &th->th_dport;
+			}
+			rewrite++;
+			break;
+		case IPPROTO_UDP:
+			bproto_sum = pd->hdr.udp->uh_sum;
+			pd->proto_sum = &pd->hdr.udp->uh_sum;
+
+			if (PF_ANEQ(saddr, &nk->addr[pd->sidx], af) ||
+			    nk->port[pd->sidx] != sport) {
+				pf_change_ap(saddr, &pd->hdr.udp->uh_sport,
+				    pd->ip_sum, &pd->hdr.udp->uh_sum,
+				    &nk->addr[pd->sidx],
+				    nk->port[pd->sidx], 1, af);
+				sport = pd->hdr.udp->uh_sport;
+				pd->sport = &pd->hdr.udp->uh_sport;
+			}
+
+			if (PF_ANEQ(daddr, &nk->addr[pd->didx], af) ||
+			    nk->port[pd->didx] != dport) {
+				pf_change_ap(daddr, &pd->hdr.udp->uh_dport,
+				    pd->ip_sum, &pd->hdr.udp->uh_sum,
+				    &nk->addr[pd->didx],
+				    nk->port[pd->didx], 1, af);
+				dport = pd->hdr.udp->uh_dport;
+				pd->dport = &pd->hdr.udp->uh_dport;
+			}
+			rewrite++;
+			break;
 #ifdef INET
-			case AF_INET:
+		case IPPROTO_ICMP:
+			nk->port[0] = nk->port[1];
+			if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET))
 				pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
-				    pd->naddr.v4.s_addr, 0);
+				    nk->addr[pd->sidx].v4.s_addr, 0);
+
+			if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET))
+				pf_change_a(&daddr->v4.s_addr, pd->ip_sum,
+				    nk->addr[pd->didx].v4.s_addr, 0);
+
+			if (nk->port[1] != pd->hdr.icmp->icmp_id) {
 				pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
-				    pd->hdr.icmp->icmp_cksum, icmpid, nport, 0);
-				pd->hdr.icmp->icmp_id = nport;
-				m_copyback(m, off, ICMP_MINLEN,
-				    (caddr_t)pd->hdr.icmp);
-				break;
+				    pd->hdr.icmp->icmp_cksum, sport,
+				    nk->port[1], 0);
+				pd->hdr.icmp->icmp_id = nk->port[1];
+				pd->sport = &pd->hdr.icmp->icmp_id;
+			}
+			m_copyback(m, off, ICMP_MINLEN, (caddr_t)pd->hdr.icmp);
+			break;
 #endif /* INET */
 #ifdef INET6
-			case AF_INET6:
+		case IPPROTO_ICMPV6:
+			nk->port[0] = nk->port[1];
+			if (PF_ANEQ(saddr, &nk->addr[pd->sidx], AF_INET6))
 				pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
-				    &pd->naddr, 0);
-				rewrite++;
-				break;
-#endif /* INET6 */
-			}
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
-		}
-	} else {
-		bport = nport = icmpid;
-		/* check incoming packet for BINAT/RDR */
-		if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
-		    saddr, icmpid, daddr, icmpid, &pd->naddr, &nport)) !=
-		    NULL) {
-			PF_ACPY(&pd->baddr, daddr, af);
+				    &nk->addr[pd->sidx], 0);
+
+			if (PF_ANEQ(daddr, &nk->addr[pd->didx], AF_INET6))
+				pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
+				    &nk->addr[pd->didx], 0);
+			rewrite++;
+			break;
+#endif /* INET */
+		default:
 			switch (af) {
 #ifdef INET
 			case AF_INET:
-				pf_change_a(&daddr->v4.s_addr,
-				    pd->ip_sum, pd->naddr.v4.s_addr, 0);
+				if (PF_ANEQ(saddr,
+				    &nk->addr[pd->sidx], AF_INET))
+					pf_change_a(&saddr->v4.s_addr,
+					    pd->ip_sum,
+					    nk->addr[pd->sidx].v4.s_addr, 0);
+
+				if (PF_ANEQ(daddr,
+				    &nk->addr[pd->didx], AF_INET))
+					pf_change_a(&daddr->v4.s_addr,
+					    pd->ip_sum,
+					    nk->addr[pd->didx].v4.s_addr, 0);
 				break;
 #endif /* INET */
 #ifdef INET6
 			case AF_INET6:
-				pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
-				    &pd->naddr, 0);
-				rewrite++;
+				if (PF_ANEQ(saddr,
+				    &nk->addr[pd->sidx], AF_INET6))
+					PF_ACPY(saddr, &nk->addr[pd->sidx], af);
+
+				if (PF_ANEQ(daddr,
+				    &nk->addr[pd->didx], AF_INET6))
+					PF_ACPY(saddr, &nk->addr[pd->didx], af);
 				break;
-#endif /* INET6 */
+#endif /* INET */
 			}
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
+			break;
 		}
+		if (nr->natpass)
+			r = NULL;
+		pd->nat_rule = nr;
 	}
 
 	while (r != NULL) {
@@ -4146,284 +3550,67 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
 		else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
 		    r->src.neg, kif))
 			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+		/* tcp/udp only. port_op always 0 in other cases */
+		else if (r->src.port_op && !pf_match_port(r->src.port_op,
+		    r->src.port[0], r->src.port[1], sport))
+			r = r->skip[PF_SKIP_SRC_PORT].ptr;
 		else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
 		    r->dst.neg, NULL))
 			r = r->skip[PF_SKIP_DST_ADDR].ptr;
+		/* tcp/udp only. port_op always 0 in other cases */
+		else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
+		    r->dst.port[0], r->dst.port[1], dport))
+			r = r->skip[PF_SKIP_DST_PORT].ptr;
+		/* icmp only. type always 0 in other cases */
 		else if (r->type && r->type != icmptype + 1)
 			r = TAILQ_NEXT(r, entries);
+		/* icmp only. type always 0 in other cases */
 		else if (r->code && r->code != icmpcode + 1)
 			r = TAILQ_NEXT(r, entries);
 		else if (r->tos && !(r->tos == pd->tos))
 			r = TAILQ_NEXT(r, entries);
 		else if (r->rule_flag & PFRULE_FRAGMENT)
 			r = TAILQ_NEXT(r, entries);
-		else if (r->prob && r->prob <= arc4random())
-			r = TAILQ_NEXT(r, entries);
-		else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
-			r = TAILQ_NEXT(r, entries);
-		else if (r->os_fingerprint != PF_OSFP_ANY)
+		else if (pd->proto == IPPROTO_TCP &&
+		    (r->flagset & th->th_flags) != r->flags)
 			r = TAILQ_NEXT(r, entries);
-		else {
-			if (r->tag)
-				tag = r->tag;
-			if (r->rtableid >= 0)
-				rtableid = r->rtableid;
-			if (r->anchor == NULL) {
-				match = 1;
-				*rm = r;
-				*am = a;
-				*rsm = ruleset;
-				if ((*rm)->quick)
-					break;
-				r = TAILQ_NEXT(r, entries);
-			} else
-				pf_step_into_anchor(&asd, &ruleset,
-				    PF_RULESET_FILTER, &r, &a, &match);
-		}
-		if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
-		    PF_RULESET_FILTER, &r, &a, &match))
-			break;
-	}
-	r = *rm;
-	a = *am;
-	ruleset = *rsm;
-
-	REASON_SET(&reason, PFRES_MATCH);
-
-	if (r->log || (nr != NULL && nr->natpass && nr->log)) {
-#ifdef INET6
-		if (rewrite)
-			m_copyback(m, off, sizeof(struct icmp6_hdr),
-			    (caddr_t)pd->hdr.icmp6);
-#endif /* INET6 */
-		PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
-		    a, ruleset, pd);
-	}
-
-	if (r->action != PF_PASS)
-		return (PF_DROP);
-
-	if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
-		REASON_SET(&reason, PFRES_MEMORY);
-		return (PF_DROP);
-	}
-
-	if (!state_icmp && (r->keep_state || nr != NULL)) {
-		/* create new state */
-		struct pf_state	*s = NULL;
-		struct pf_src_node *sn = NULL;
-
-		/* check maximums */
-		if (r->max_states && (r->states >= r->max_states)) {
-			pf_status.lcounters[LCNT_STATES]++;
-			REASON_SET(&reason, PFRES_MAXSTATES);
-			goto cleanup;
-		}
-		/* src node for filter rule */
-		if ((r->rule_flag & PFRULE_SRCTRACK ||
-		    r->rpool.opts & PF_POOL_STICKYADDR) &&
-		    pf_insert_src_node(&sn, r, saddr, af) != 0) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		/* src node for translation rule */
-		if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
-		    ((direction == PF_OUT &&
-		    pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
-		    (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		s = pool_get(&pf_state_pl, PR_NOWAIT);
-		if (s == NULL) {
-			REASON_SET(&reason, PFRES_MEMORY);
-cleanup:
-			if (sn != NULL && sn->states == 0 && sn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, sn);
-			}
-			if (nsn != sn && nsn != NULL && nsn->states == 0 &&
-			    nsn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, nsn);
-			}
-			return (PF_DROP);
-		}
-		bzero(s, sizeof(*s));
-		s->rule.ptr = r;
-		s->nat_rule.ptr = nr;
-		s->anchor.ptr = a;
-		STATE_INC_COUNTERS(s);
-		if (r->allow_opts)
-			s->state_flags |= PFSTATE_ALLOWOPTS;
- 		if (r->rule_flag & PFRULE_STATESLOPPY)
-			s->state_flags |= PFSTATE_SLOPPY;
-		s->log = r->log & PF_LOG_ALL;
-		if (nr != NULL)
-			s->log |= nr->log & PF_LOG_ALL;
-		s->proto = pd->proto;
-		s->direction = direction;
-		s->af = af;
-		if (direction == PF_OUT) {
-			PF_ACPY(&s->gwy.addr, saddr, af);
-			s->gwy.port = nport;
-			PF_ACPY(&s->ext.addr, daddr, af);
-			s->ext.port = 0;
-			if (nr != NULL) {
-				PF_ACPY(&s->lan.addr, &pd->baddr, af);
-				s->lan.port = bport;
-			} else {
-				PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
-				s->lan.port = s->gwy.port;
-			}
-		} else {
-			PF_ACPY(&s->lan.addr, daddr, af);
-			s->lan.port = nport;
-			PF_ACPY(&s->ext.addr, saddr, af);
-			s->ext.port = 0; 
-			if (nr != NULL) {
-				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
-				s->gwy.port = bport;
-			} else {
-				PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
-				s->gwy.port = s->lan.port;
-			}
-		}
-		s->creation = time_second;
-		s->expire = time_second;
-		s->timeout = PFTM_ICMP_FIRST_PACKET;
-		pf_set_rt_ifp(s, saddr);
-		if (sn != NULL) {
-			s->src_node = sn;
-			s->src_node->states++;
-		}
-		if (nsn != NULL) {
-			PF_ACPY(&nsn->raddr, &pd->naddr, af);
-			s->nat_src_node = nsn;
-			s->nat_src_node->states++;
-		}
-		if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
-			REASON_SET(&reason, PFRES_STATEINS);
-			pf_src_tree_remove_state(s);
-			STATE_DEC_COUNTERS(s);
-			pool_put(&pf_state_pl, s);
-			return (PF_DROP);
-		} else
-			*sm = s;
-		if (tag > 0) {
-			pf_tag_ref(tag);
-			s->tag = tag;
-		}
-	}
-
-#ifdef INET6
-	/* copy back packet headers if we performed IPv6 NAT operations */
-	if (rewrite)
-		m_copyback(m, off, sizeof(struct icmp6_hdr),
-		    (caddr_t)pd->hdr.icmp6);
-#endif /* INET6 */
-
-	return (PF_PASS);
-}
-
-int
-pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
-    struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
-    struct pf_rule **am, struct pf_ruleset **rsm, struct ifqueue *ifq)
-{
-	struct pf_rule		*nr = NULL;
-	struct pf_rule		*r, *a = NULL;
-	struct pf_ruleset	*ruleset = NULL;
-	struct pf_src_node	*nsn = NULL;
-	struct pf_addr		*saddr = pd->src, *daddr = pd->dst;
-	sa_family_t		 af = pd->af;
-	u_short			 reason;
-	int			 tag = -1, rtableid = -1;
-	int			 asd = 0;
-	int			 match = 0;
-
-	if (pf_check_congestion(ifq)) {
-		REASON_SET(&reason, PFRES_CONGEST);
-		return (PF_DROP);
-	}
-
-	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
-
-	if (direction == PF_OUT) {
-		/* check outgoing packet for BINAT/NAT */
-		if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
-		    saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
-			PF_ACPY(&pd->baddr, saddr, af);
-			switch (af) {
-#ifdef INET
-			case AF_INET:
-				pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
-				    pd->naddr.v4.s_addr, 0);
-				break;
-#endif /* INET */
-#ifdef INET6
-			case AF_INET6:
-				PF_ACPY(saddr, &pd->naddr, af);
-				break;
-#endif /* INET6 */
-			}
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
-		}
-	} else {
-		/* check incoming packet for BINAT/RDR */
-		if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
-		    saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
-			PF_ACPY(&pd->baddr, daddr, af);
-			switch (af) {
-#ifdef INET
-			case AF_INET:
-				pf_change_a(&daddr->v4.s_addr,
-				    pd->ip_sum, pd->naddr.v4.s_addr, 0);
-				break;
-#endif /* INET */
-#ifdef INET6
-			case AF_INET6:
-				PF_ACPY(daddr, &pd->naddr, af);
-				break;
-#endif /* INET6 */
-			}
-			if (nr->natpass)
-				r = NULL;
-			pd->nat_rule = nr;
-		}
-	}
-
-	while (r != NULL) {
-		r->evaluations++;
-		if (pfi_kif_match(r->kif, kif) == r->ifnot)
-			r = r->skip[PF_SKIP_IFP].ptr;
-		else if (r->direction && r->direction != direction)
-			r = r->skip[PF_SKIP_DIR].ptr;
-		else if (r->af && r->af != af)
-			r = r->skip[PF_SKIP_AF].ptr;
-		else if (r->proto && r->proto != pd->proto)
-			r = r->skip[PF_SKIP_PROTO].ptr;
-		else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
-		    r->src.neg, kif))
-			r = r->skip[PF_SKIP_SRC_ADDR].ptr;
-		else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
-		    r->dst.neg, NULL))
-			r = r->skip[PF_SKIP_DST_ADDR].ptr;
-		else if (r->tos && !(r->tos == pd->tos))
+		/* tcp/udp only. uid.op always 0 in other cases */
+		else if (r->uid.op && (pd->lookup.done || (pd->lookup.done =
+#ifdef __FreeBSD__
+		    pf_socket_lookup(direction, pd, inp), 1)) &&
+#else
+		    pf_socket_lookup(direction, pd), 1)) &&
+#endif
+		    !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
+		    pd->lookup.uid))
 			r = TAILQ_NEXT(r, entries);
-		else if (r->rule_flag & PFRULE_FRAGMENT)
+		/* tcp/udp only. gid.op always 0 in other cases */
+		else if (r->gid.op && (pd->lookup.done || (pd->lookup.done =
+#ifdef __FreeBSD__
+		    pf_socket_lookup(direction, pd, inp), 1)) &&
+#else
+		    pf_socket_lookup(direction, pd), 1)) &&
+#endif
+		    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
+		    pd->lookup.gid))
 			r = TAILQ_NEXT(r, entries);
-		else if (r->prob && r->prob <= arc4random())
+		else if (r->prob &&
+#ifdef __FreeBSD__
+		    r->prob <= arc4random())
+#else
+		    r->prob <= arc4random_uniform(UINT_MAX - 1) + 1)
+#endif
 			r = TAILQ_NEXT(r, entries);
-		else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+#ifdef __FreeBSD__
+		else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
+#else
+		else if (r->match_tag && !pf_match_tag(m, r, &tag))
+#endif
 			r = TAILQ_NEXT(r, entries);
-		else if (r->os_fingerprint != PF_OSFP_ANY)
+		else if (r->os_fingerprint != PF_OSFP_ANY &&
+		    (pd->proto != IPPROTO_TCP || !pf_osfp_match(
+		    pf_osfp_fingerprint(pd, m, off, th),
+		    r->os_fingerprint)))
 			r = TAILQ_NEXT(r, entries);
 		else {
 			if (r->tag)
@@ -4452,157 +3639,428 @@ pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
 
 	REASON_SET(&reason, PFRES_MATCH);
 
-	if (r->log || (nr != NULL && nr->natpass && nr->log))
+	if (r->log || (nr != NULL && nr->log)) {
+		if (rewrite)
+			m_copyback(m, off, hdrlen, pd->hdr.any);
 		PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
 		    a, ruleset, pd);
+	}
 
 	if ((r->action == PF_DROP) &&
-	    ((r->rule_flag & PFRULE_RETURNICMP) ||
+	    ((r->rule_flag & PFRULE_RETURNRST) ||
+	    (r->rule_flag & PFRULE_RETURNICMP) ||
 	    (r->rule_flag & PFRULE_RETURN))) {
-		struct pf_addr *a = NULL;
-
+		/* undo NAT changes, if they have taken place */
 		if (nr != NULL) {
-			if (direction == PF_OUT)
-				a = saddr;
-			else
-				a = daddr;
-		}
-		if (a != NULL) {
+			PF_ACPY(saddr, &sk->addr[pd->sidx], af);
+			PF_ACPY(daddr, &sk->addr[pd->didx], af);
+			if (pd->sport)
+				*pd->sport = sk->port[pd->sidx];
+			if (pd->dport)
+				*pd->dport = sk->port[pd->didx];
+			if (pd->proto_sum)
+				*pd->proto_sum = bproto_sum;
+			if (pd->ip_sum)
+				*pd->ip_sum = bip_sum;
+			m_copyback(m, off, hdrlen, pd->hdr.any);
+		}
+		if (pd->proto == IPPROTO_TCP &&
+		    ((r->rule_flag & PFRULE_RETURNRST) ||
+		    (r->rule_flag & PFRULE_RETURN)) &&
+		    !(th->th_flags & TH_RST)) {
+			u_int32_t	 ack = ntohl(th->th_seq) + pd->p_len;
+			int		 len = 0;
+#ifdef INET
+			struct ip	*h4;
+#endif
+#ifdef INET6
+			struct ip6_hdr	*h6;
+#endif
+
 			switch (af) {
 #ifdef INET
 			case AF_INET:
-				pf_change_a(&a->v4.s_addr, pd->ip_sum,
-				    pd->baddr.v4.s_addr, 0);
+				h4 = mtod(m, struct ip *);
+				len = ntohs(h4->ip_len) - off;
 				break;
-#endif /* INET */
+#endif
 #ifdef INET6
 			case AF_INET6:
-				PF_ACPY(a, &pd->baddr, af);
+				h6 = mtod(m, struct ip6_hdr *);
+				len = ntohs(h6->ip6_plen) - (off - sizeof(*h6));
 				break;
-#endif /* INET6 */
+#endif
+			}
+
+			if (pf_check_proto_cksum(m, off, len, IPPROTO_TCP, af))
+				REASON_SET(&reason, PFRES_PROTCKSUM);
+			else {
+				if (th->th_flags & TH_SYN)
+					ack++;
+				if (th->th_flags & TH_FIN)
+					ack++;
+#ifdef __FreeBSD__
+				pf_send_tcp(m, r, af, pd->dst,
+#else
+				pf_send_tcp(r, af, pd->dst,
+#endif
+				    pd->src, th->th_dport, th->th_sport,
+				    ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
+				    r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
 			}
-		}
-		if ((af == AF_INET) && r->return_icmp)
+		} else if (pd->proto != IPPROTO_ICMP && af == AF_INET &&
+		    r->return_icmp)
 			pf_send_icmp(m, r->return_icmp >> 8,
 			    r->return_icmp & 255, af, r);
-		else if ((af == AF_INET6) && r->return_icmp6)
+		else if (pd->proto != IPPROTO_ICMPV6 && af == AF_INET6 &&
+		    r->return_icmp6)
 			pf_send_icmp(m, r->return_icmp6 >> 8,
 			    r->return_icmp6 & 255, af, r);
 	}
 
-	if (r->action != PF_PASS)
-		return (PF_DROP);
+	if (r->action == PF_DROP)
+		goto cleanup;
 
-	if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
+#ifdef __FreeBSD__
+	if (pf_tag_packet(m, tag, rtableid, pd->pf_mtag)) {
+#else
+	if (pf_tag_packet(m, tag, rtableid)) {
+#endif
 		REASON_SET(&reason, PFRES_MEMORY);
-		return (PF_DROP);
+		goto cleanup;
 	}
 
-	if (r->keep_state || nr != NULL) {
-		/* create new state */
-		struct pf_state	*s = NULL;
-		struct pf_src_node *sn = NULL;
+	if (!state_icmp && (r->keep_state || nr != NULL ||
+	    (pd->flags & PFDESC_TCP_NORM))) {
+		int action;
+		action = pf_create_state(r, nr, a, pd, nsn, skw, sks, nk, sk, m,
+		    off, sport, dport, &rewrite, kif, sm, tag, bproto_sum,
+		    bip_sum, hdrlen);
+		if (action != PF_PASS)
+			return (action);
+	} else {
+#ifdef __FreeBSD__
+		if (sk != NULL)
+			pool_put(&V_pf_state_key_pl, sk);
+		if (nk != NULL)
+			pool_put(&V_pf_state_key_pl, nk);
+#else
+		if (sk != NULL)
+			pool_put(&pf_state_key_pl, sk);
+		if (nk != NULL)
+			pool_put(&pf_state_key_pl, nk);
+#endif
+	}
+
+	/* copy back packet headers if we performed NAT operations */
+	if (rewrite)
+		m_copyback(m, off, hdrlen, pd->hdr.any);
+
+#if NPFSYNC > 0
+	if (*sm != NULL && !ISSET((*sm)->state_flags, PFSTATE_NOSYNC) &&
+#ifdef __FreeBSD__
+	    direction == PF_OUT && pfsync_up_ptr != NULL && pfsync_up_ptr()) {
+#else
+	    direction == PF_OUT && pfsync_up()) {
+#endif
+		/*
+		 * We want the state created, but we dont
+		 * want to send this in case a partner
+		 * firewall has to know about it to allow
+		 * replies through it.
+		 */
+#ifdef __FreeBSD__
+		if (pfsync_defer_ptr != NULL)
+			pfsync_defer_ptr(*sm, m);
+#else
+		if (pfsync_defer(*sm, m))
+#endif
+			return (PF_DEFER);
+	}
+#endif
+
+	return (PF_PASS);
 
-		/* check maximums */
-		if (r->max_states && (r->states >= r->max_states)) {
-			pf_status.lcounters[LCNT_STATES]++;
-			REASON_SET(&reason, PFRES_MAXSTATES);
-			goto cleanup;
-		}
-		/* src node for filter rule */
-		if ((r->rule_flag & PFRULE_SRCTRACK ||
-		    r->rpool.opts & PF_POOL_STICKYADDR) &&
-		    pf_insert_src_node(&sn, r, saddr, af) != 0) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		/* src node for translation rule */
-		if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
-		    ((direction == PF_OUT &&
-		    pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
-		    (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
-			REASON_SET(&reason, PFRES_SRCLIMIT);
-			goto cleanup;
-		}
-		s = pool_get(&pf_state_pl, PR_NOWAIT);
-		if (s == NULL) {
-			REASON_SET(&reason, PFRES_MEMORY);
 cleanup:
-			if (sn != NULL && sn->states == 0 && sn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, sn);
-			}
-			if (nsn != sn && nsn != NULL && nsn->states == 0 &&
-			    nsn->expire == 0) {
-				RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
-				pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
-				pf_status.src_nodes--;
-				pool_put(&pf_src_tree_pl, nsn);
-			}
-			return (PF_DROP);
+#ifdef __FreeBSD__
+	if (sk != NULL)
+		pool_put(&V_pf_state_key_pl, sk);
+	if (nk != NULL)
+		pool_put(&V_pf_state_key_pl, nk);
+#else
+	if (sk != NULL)
+		pool_put(&pf_state_key_pl, sk);
+	if (nk != NULL)
+		pool_put(&pf_state_key_pl, nk);
+#endif
+	return (PF_DROP);
+}
+
+static __inline int
+pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a,
+    struct pf_pdesc *pd, struct pf_src_node *nsn, struct pf_state_key *skw,
+    struct pf_state_key *sks, struct pf_state_key *nk, struct pf_state_key *sk,
+    struct mbuf *m, int off, u_int16_t sport, u_int16_t dport, int *rewrite,
+    struct pfi_kif *kif, struct pf_state **sm, int tag, u_int16_t bproto_sum,
+    u_int16_t bip_sum, int hdrlen)
+{
+	struct pf_state		*s = NULL;
+	struct pf_src_node	*sn = NULL;
+	struct tcphdr		*th = pd->hdr.tcp;
+#ifdef __FreeBSD__
+	u_int16_t		 mss = V_tcp_mssdflt;
+#else
+	u_int16_t		 mss = tcp_mssdflt;
+#endif
+	u_short			 reason;
+
+	/* check maximums */
+	if (r->max_states && (r->states_cur >= r->max_states)) {
+#ifdef __FreeBSD__
+		V_pf_status.lcounters[LCNT_STATES]++;
+#else
+		pf_status.lcounters[LCNT_STATES]++;
+#endif
+		REASON_SET(&reason, PFRES_MAXSTATES);
+		return (PF_DROP);
+	}
+	/* src node for filter rule */
+	if ((r->rule_flag & PFRULE_SRCTRACK ||
+	    r->rpool.opts & PF_POOL_STICKYADDR) &&
+	    pf_insert_src_node(&sn, r, pd->src, pd->af) != 0) {
+		REASON_SET(&reason, PFRES_SRCLIMIT);
+		goto csfailed;
+	}
+	/* src node for translation rule */
+	if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
+	    pf_insert_src_node(&nsn, nr, &sk->addr[pd->sidx], pd->af)) {
+		REASON_SET(&reason, PFRES_SRCLIMIT);
+		goto csfailed;
+	}
+#ifdef __FreeBSD__
+	s = pool_get(&V_pf_state_pl, PR_NOWAIT | PR_ZERO);
+#else
+	s = pool_get(&pf_state_pl, PR_NOWAIT | PR_ZERO);
+#endif
+	if (s == NULL) {
+		REASON_SET(&reason, PFRES_MEMORY);
+		goto csfailed;
+	}
+	s->rule.ptr = r;
+	s->nat_rule.ptr = nr;
+	s->anchor.ptr = a;
+	STATE_INC_COUNTERS(s);
+	if (r->allow_opts)
+		s->state_flags |= PFSTATE_ALLOWOPTS;
+	if (r->rule_flag & PFRULE_STATESLOPPY)
+		s->state_flags |= PFSTATE_SLOPPY;
+	if (r->rule_flag & PFRULE_PFLOW)
+		s->state_flags |= PFSTATE_PFLOW;
+	s->log = r->log & PF_LOG_ALL;
+	s->sync_state = PFSYNC_S_NONE;
+	if (nr != NULL)
+		s->log |= nr->log & PF_LOG_ALL;
+	switch (pd->proto) {
+	case IPPROTO_TCP:
+		s->src.seqlo = ntohl(th->th_seq);
+		s->src.seqhi = s->src.seqlo + pd->p_len + 1;
+		if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
+		    r->keep_state == PF_STATE_MODULATE) {
+			/* Generate sequence number modulator */
+			if ((s->src.seqdiff = pf_tcp_iss(pd) - s->src.seqlo) ==
+			    0)
+				s->src.seqdiff = 1;
+			pf_change_a(&th->th_seq, &th->th_sum,
+			    htonl(s->src.seqlo + s->src.seqdiff), 0);
+			*rewrite = 1;
+		} else
+			s->src.seqdiff = 0;
+		if (th->th_flags & TH_SYN) {
+			s->src.seqhi++;
+			s->src.wscale = pf_get_wscale(m, off,
+			    th->th_off, pd->af);
 		}
-		bzero(s, sizeof(*s));
-		s->rule.ptr = r;
-		s->nat_rule.ptr = nr;
-		s->anchor.ptr = a;
-		STATE_INC_COUNTERS(s);
-		if (r->allow_opts)
-			s->state_flags |= PFSTATE_ALLOWOPTS;
- 		if (r->rule_flag & PFRULE_STATESLOPPY)
-			s->state_flags |= PFSTATE_SLOPPY;
-		s->log = r->log & PF_LOG_ALL;
-		if (nr != NULL)
-			s->log |= nr->log & PF_LOG_ALL;
-		s->proto = pd->proto;
-		s->direction = direction;
-		s->af = af;
-		if (direction == PF_OUT) {
-			PF_ACPY(&s->gwy.addr, saddr, af);
-			PF_ACPY(&s->ext.addr, daddr, af);
-			if (nr != NULL)
-				PF_ACPY(&s->lan.addr, &pd->baddr, af);
-			else
-				PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
-		} else {
-			PF_ACPY(&s->lan.addr, daddr, af);
-			PF_ACPY(&s->ext.addr, saddr, af);
-			if (nr != NULL)
-				PF_ACPY(&s->gwy.addr, &pd->baddr, af);
-			else
-				PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
+		s->src.max_win = MAX(ntohs(th->th_win), 1);
+		if (s->src.wscale & PF_WSCALE_MASK) {
+			/* Remove scale factor from initial window */
+			int win = s->src.max_win;
+			win += 1 << (s->src.wscale & PF_WSCALE_MASK);
+			s->src.max_win = (win - 1) >>
+			    (s->src.wscale & PF_WSCALE_MASK);
 		}
+		if (th->th_flags & TH_FIN)
+			s->src.seqhi++;
+		s->dst.seqhi = 1;
+		s->dst.max_win = 1;
+		s->src.state = TCPS_SYN_SENT;
+		s->dst.state = TCPS_CLOSED;
+		s->timeout = PFTM_TCP_FIRST_PACKET;
+		break;
+	case IPPROTO_UDP:
+		s->src.state = PFUDPS_SINGLE;
+		s->dst.state = PFUDPS_NO_TRAFFIC;
+		s->timeout = PFTM_UDP_FIRST_PACKET;
+		break;
+	case IPPROTO_ICMP:
+#ifdef INET6
+	case IPPROTO_ICMPV6:
+#endif
+		s->timeout = PFTM_ICMP_FIRST_PACKET;
+		break;
+	default:
 		s->src.state = PFOTHERS_SINGLE;
 		s->dst.state = PFOTHERS_NO_TRAFFIC;
-		s->creation = time_second;
-		s->expire = time_second;
 		s->timeout = PFTM_OTHER_FIRST_PACKET;
-		pf_set_rt_ifp(s, saddr);
-		if (sn != NULL) {
-			s->src_node = sn;
-			s->src_node->states++;
-		}
-		if (nsn != NULL) {
-			PF_ACPY(&nsn->raddr, &pd->naddr, af);
-			s->nat_src_node = nsn;
-			s->nat_src_node->states++;
+	}
+
+	s->creation = time_second;
+	s->expire = time_second;
+
+	if (sn != NULL) {
+		s->src_node = sn;
+		s->src_node->states++;
+	}
+	if (nsn != NULL) {
+		/* XXX We only modify one side for now. */
+		PF_ACPY(&nsn->raddr, &nk->addr[1], pd->af);
+		s->nat_src_node = nsn;
+		s->nat_src_node->states++;
+	}
+	if (pd->proto == IPPROTO_TCP) {
+		if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
+		    off, pd, th, &s->src, &s->dst)) {
+			REASON_SET(&reason, PFRES_MEMORY);
+			pf_src_tree_remove_state(s);
+			STATE_DEC_COUNTERS(s);
+#ifdef __FreeBSD__
+			pool_put(&V_pf_state_pl, s);
+#else
+			pool_put(&pf_state_pl, s);
+#endif
+			return (PF_DROP);
 		}
-		if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
-			REASON_SET(&reason, PFRES_STATEINS);
+		if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
+		    pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
+		    &s->src, &s->dst, rewrite)) {
+			/* This really shouldn't happen!!! */
+			DPFPRINTF(PF_DEBUG_URGENT,
+			    ("pf_normalize_tcp_stateful failed on first pkt"));
+			pf_normalize_tcp_cleanup(s);
 			pf_src_tree_remove_state(s);
 			STATE_DEC_COUNTERS(s);
+#ifdef __FreeBSD__
+			pool_put(&V_pf_state_pl, s);
+#else
 			pool_put(&pf_state_pl, s);
+#endif
 			return (PF_DROP);
-		} else
-			*sm = s;
-		if (tag > 0) {
-			pf_tag_ref(tag);
-			s->tag = tag;
 		}
 	}
+	s->direction = pd->dir;
+
+	if (sk == NULL && pf_state_key_setup(pd, nr, &skw, &sks, &sk, &nk,
+	    pd->src, pd->dst, sport, dport))
+		goto csfailed;
+
+	if (pf_state_insert(BOUND_IFACE(r, kif), skw, sks, s)) {
+		if (pd->proto == IPPROTO_TCP)
+			pf_normalize_tcp_cleanup(s);
+		REASON_SET(&reason, PFRES_STATEINS);
+		pf_src_tree_remove_state(s);
+		STATE_DEC_COUNTERS(s);
+#ifdef __FreeBSD__
+		pool_put(&V_pf_state_pl, s);
+#else
+		pool_put(&pf_state_pl, s);
+#endif
+		return (PF_DROP);
+	} else
+		*sm = s;
+
+	pf_set_rt_ifp(s, pd->src);	/* needs s->state_key set */
+	if (tag > 0) {
+		pf_tag_ref(tag);
+		s->tag = tag;
+	}
+	if (pd->proto == IPPROTO_TCP && (th->th_flags & (TH_SYN|TH_ACK)) ==
+	    TH_SYN && r->keep_state == PF_STATE_SYNPROXY) {
+		s->src.state = PF_TCPS_PROXY_SRC;
+		/* undo NAT changes, if they have taken place */
+		if (nr != NULL) {
+			struct pf_state_key *skt = s->key[PF_SK_WIRE];
+			if (pd->dir == PF_OUT)
+				skt = s->key[PF_SK_STACK];
+			PF_ACPY(pd->src, &skt->addr[pd->sidx], pd->af);
+			PF_ACPY(pd->dst, &skt->addr[pd->didx], pd->af);
+			if (pd->sport)
+				*pd->sport = skt->port[pd->sidx];
+			if (pd->dport)
+				*pd->dport = skt->port[pd->didx];
+			if (pd->proto_sum)
+				*pd->proto_sum = bproto_sum;
+			if (pd->ip_sum)
+				*pd->ip_sum = bip_sum;
+			m_copyback(m, off, hdrlen, pd->hdr.any);
+		}
+		s->src.seqhi = htonl(arc4random());
+		/* Find mss option */
+		mss = pf_get_mss(m, off, th->th_off, pd->af);
+		mss = pf_calc_mss(pd->src, pd->af, mss);
+		mss = pf_calc_mss(pd->dst, pd->af, mss);
+		s->src.mss = mss;
+#ifdef __FreeBSD__
+		pf_send_tcp(NULL, r, pd->af, pd->dst, pd->src, th->th_dport,
+#else
+		pf_send_tcp(r, pd->af, pd->dst, pd->src, th->th_dport,
+#endif
+		    th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
+		    TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
+		REASON_SET(&reason, PFRES_SYNPROXY);
+		return (PF_SYNPROXY_DROP);
+	}
 
 	return (PF_PASS);
+
+csfailed:
+#ifdef __FreeBSD__
+	if (sk != NULL)
+		pool_put(&V_pf_state_key_pl, sk);
+	if (nk != NULL)
+		pool_put(&V_pf_state_key_pl, nk);
+#else
+	if (sk != NULL)
+		pool_put(&pf_state_key_pl, sk);
+	if (nk != NULL)
+		pool_put(&pf_state_key_pl, nk);
+#endif
+
+	if (sn != NULL && sn->states == 0 && sn->expire == 0) {
+#ifdef __FreeBSD__
+		RB_REMOVE(pf_src_tree, &V_tree_src_tracking, sn);
+		V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+		V_pf_status.src_nodes--;
+		pool_put(&V_pf_src_tree_pl, sn);
+#else
+		RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
+		pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+		pf_status.src_nodes--;
+		pool_put(&pf_src_tree_pl, sn);
+#endif
+	}
+	if (nsn != sn && nsn != NULL && nsn->states == 0 && nsn->expire == 0) {
+#ifdef __FreeBSD__
+		RB_REMOVE(pf_src_tree, &V_tree_src_tracking, nsn);
+		V_pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+		V_pf_status.src_nodes--;
+		pool_put(&V_pf_src_tree_pl, nsn);
+#else
+		RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
+		pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+		pf_status.src_nodes--;
+		pool_put(&pf_src_tree_pl, nsn);
+#endif
+	}
+	return (PF_DROP);
 }
 
 int
@@ -4649,9 +4107,14 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
 		    pd->proto == IPPROTO_ICMPV6) &&
 		    (r->type || r->code))
 			r = TAILQ_NEXT(r, entries);
-		else if (r->prob && r->prob <= arc4random())
+		else if (r->prob && r->prob <=
+		    (arc4random() % (UINT_MAX - 1) + 1))
 			r = TAILQ_NEXT(r, entries);
-		else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+#ifdef __FreeBSD__
+		else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
+#else
+		else if (r->match_tag && !pf_match_tag(m, r, &tag))
+#endif
 			r = TAILQ_NEXT(r, entries);
 		else {
 			if (r->anchor == NULL) {
@@ -4683,7 +4146,11 @@ pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
 	if (r->action != PF_PASS)
 		return (PF_DROP);
 
-	if (pf_tag_packet(m, pd->pf_mtag, tag, -1)) {
+#ifdef __FreeBSD__
+	if (pf_tag_packet(m, tag, -1, pd->pf_mtag)) {
+#else
+	if (pf_tag_packet(m, tag, -1)) {
+#endif
 		REASON_SET(&reason, PFRES_MEMORY);
 		return (PF_DROP);
 	}
@@ -4696,11 +4163,11 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 	struct pf_state **state, struct pfi_kif *kif, struct mbuf *m, int off,
 	struct pf_pdesc *pd, u_short *reason, int *copyback)
 {
- 	struct tcphdr		*th = pd->hdr.tcp;
- 	u_int16_t		 win = ntohs(th->th_win);
- 	u_int32_t		 ack, end, seq, orig_seq;
- 	u_int8_t		 sws, dws;
- 	int			 ackskew;
+	struct tcphdr		*th = pd->hdr.tcp;
+	u_int16_t		 win = ntohs(th->th_win);
+	u_int32_t		 ack, end, seq, orig_seq;
+	u_int8_t		 sws, dws;
+	int			 ackskew;
 
 	if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) {
 		sws = src->wscale & PF_WSCALE_MASK;
@@ -4728,13 +4195,9 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 
 		/* Deferred generation of sequence number modulator */
 		if (dst->seqdiff && !src->seqdiff) {
-#ifdef __FreeBSD__
-			while ((src->seqdiff = pf_new_isn(*state) - seq) == 0)
-				;
-#else
-			while ((src->seqdiff = tcp_rndiss_next() - seq) == 0)
+			/* use random iss for the TCP server */
+			while ((src->seqdiff = arc4random() - seq) == 0)
 				;
-#endif
 			ack = ntohl(th->th_ack) - dst->seqdiff;
 			pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
 			    src->seqdiff), 0);
@@ -4841,7 +4304,7 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 	}
 
 
-#define MAXACKWINDOW (0xffff + 1500)	/* 1500 is an arbitrary fudge factor */
+#define	MAXACKWINDOW (0xffff + 1500)	/* 1500 is an arbitrary fudge factor */
 	if (SEQ_GEQ(src->seqhi, end) &&
 	    /* Last octet inside other's window space */
 	    SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) &&
@@ -4851,7 +4314,8 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 	    (ackskew <= (MAXACKWINDOW << sws)) &&
 	    /* Acking not more than one window forward */
 	    ((th->th_flags & TH_RST) == 0 || orig_seq == src->seqlo ||
-	    (orig_seq == src->seqlo + 1) || (pd->flags & PFDESC_IP_REAS) == 0)) {
+	    (orig_seq == src->seqlo + 1) || (orig_seq + 1 == src->seqlo) ||
+	    (pd->flags & PFDESC_IP_REAS) == 0)) {
 	    /* Require an exact/+1 sequence match on resets when possible */
 
 		if (dst->scrub || src->scrub) {
@@ -4941,19 +4405,25 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 		 * and keep updating the state TTL.
 		 */
 
+#ifdef __FreeBSD__
+		if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 		if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 			printf("pf: loose state match: ");
 			pf_print_state(*state);
 			pf_print_flags(th->th_flags);
 			printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
-			    "pkts=%llu:%llu\n", seq, orig_seq, ack, pd->p_len,
+			    "pkts=%llu:%llu dir=%s,%s\n", seq, orig_seq, ack,
 #ifdef __FreeBSD__
-			    ackskew, (unsigned long long)(*state)->packets[0],
-			    (unsigned long long)(*state)->packets[1]);
+			    pd->p_len, ackskew, (unsigned long long)(*state)->packets[0],
+			    (unsigned long long)(*state)->packets[1],
 #else
-			    ackskew, (*state)->packets[0],
-			    (*state)->packets[1]);
+			    pd->p_len, ackskew, (*state)->packets[0],
+			    (*state)->packets[1],
 #endif
+			    pd->dir == PF_IN ? "in" : "out",
+			    pd->dir == (*state)->direction ? "fwd" : "rev");
 		}
 
 		if (dst->scrub || src->scrub) {
@@ -4991,7 +4461,7 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 			/* Send RST for state mismatches during handshake */
 			if (!(th->th_flags & TH_RST))
 #ifdef __FreeBSD__
-				pf_send_tcp(m, (*state)->rule.ptr, pd->af,
+				pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
 #else
 				pf_send_tcp((*state)->rule.ptr, pd->af,
 #endif
@@ -5003,16 +4473,16 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 			src->seqlo = 0;
 			src->seqhi = 1;
 			src->max_win = 1;
+#ifdef __FreeBSD__
+		} else if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 		} else if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 			printf("pf: BAD state: ");
 			pf_print_state(*state);
 			pf_print_flags(th->th_flags);
 			printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
-#ifdef notyet
 			    "pkts=%llu:%llu dir=%s,%s\n",
-#else
-			    "pkts=%llu:%llu%s\n",
-#endif
 			    seq, orig_seq, ack, pd->p_len, ackskew,
 #ifdef __FreeBSD__
 			    (unsigned long long)(*state)->packets[0],
@@ -5020,12 +4490,8 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 #else
 			    (*state)->packets[0], (*state)->packets[1],
 #endif
-#ifdef notyet
-			    direction == PF_IN ? "in" : "out",
-			    direction == (*state)->direction ? "fwd" : "rev");
-#else
-			    "");
-#endif
+			    pd->dir == PF_IN ? "in" : "out",
+			    pd->dir == (*state)->direction ? "fwd" : "rev");
 			printf("pf: State failure on: %c %c %c %c | %c %c\n",
 			    SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
 			    SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ?
@@ -5039,7 +4505,6 @@ pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
 		return (PF_DROP);
 	}
 
-	/* Any packets which have gotten here are to be passed */
 	return (PF_PASS);
 }
 
@@ -5114,32 +4579,36 @@ pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst,
 	return (PF_PASS);
 }
 
-
 int
 pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
     struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
     u_short *reason)
 {
-	struct pf_state_cmp	 key;
+	struct pf_state_key_cmp	 key;
 	struct tcphdr		*th = pd->hdr.tcp;
 	int			 copyback = 0;
 	struct pf_state_peer	*src, *dst;
+	struct pf_state_key	*sk;
 
 	key.af = pd->af;
 	key.proto = IPPROTO_TCP;
-	if (direction == PF_IN)	{
-		PF_ACPY(&key.ext.addr, pd->src, key.af);
-		PF_ACPY(&key.gwy.addr, pd->dst, key.af);
-		key.ext.port = th->th_sport;
-		key.gwy.port = th->th_dport;
-	} else {
-		PF_ACPY(&key.lan.addr, pd->src, key.af);
-		PF_ACPY(&key.ext.addr, pd->dst, key.af);
-		key.lan.port = th->th_sport;
-		key.ext.port = th->th_dport;
+	if (direction == PF_IN)	{	/* wire side, straight */
+		PF_ACPY(&key.addr[0], pd->src, key.af);
+		PF_ACPY(&key.addr[1], pd->dst, key.af);
+		key.port[0] = th->th_sport;
+		key.port[1] = th->th_dport;
+	} else {			/* stack side, reverse */
+		PF_ACPY(&key.addr[1], pd->src, key.af);
+		PF_ACPY(&key.addr[0], pd->dst, key.af);
+		key.port[1] = th->th_sport;
+		key.port[0] = th->th_dport;
 	}
 
-	STATE_LOOKUP();
+#ifdef __FreeBSD__
+	STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+	STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
 	if (direction == (*state)->direction) {
 		src = &(*state)->src;
@@ -5149,6 +4618,8 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
 		dst = &(*state)->src;
 	}
 
+	sk = (*state)->key[pd->didx];
+
 	if ((*state)->src.state == PF_TCPS_PROXY_SRC) {
 		if (direction != (*state)->direction) {
 			REASON_SET(reason, PFRES_SYNPROXY);
@@ -5183,15 +4654,6 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
 			(*state)->src.state = PF_TCPS_PROXY_DST;
 	}
 	if ((*state)->src.state == PF_TCPS_PROXY_DST) {
-		struct pf_state_host *src, *dst;
-
-		if (direction == PF_OUT) {
-			src = &(*state)->gwy;
-			dst = &(*state)->ext;
-		} else {
-			src = &(*state)->ext;
-			dst = &(*state)->lan;
-		}
 		if (direction == (*state)->direction) {
 			if (((th->th_flags & (TH_SYN|TH_ACK)) != TH_ACK) ||
 			    (ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
@@ -5204,11 +4666,11 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
 				(*state)->dst.seqhi = htonl(arc4random());
 #ifdef __FreeBSD__
 			pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
-			    &src->addr,
 #else
-			pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
+			pf_send_tcp((*state)->rule.ptr, pd->af,
 #endif
-			    &dst->addr, src->port, dst->port,
+			    &sk->addr[pd->sidx], &sk->addr[pd->didx],
+			    sk->port[pd->sidx], sk->port[pd->didx],
 			    (*state)->dst.seqhi, 0, TH_SYN, 0,
 			    (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
 			REASON_SET(reason, PFRES_SYNPROXY);
@@ -5232,11 +4694,11 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
 			    (*state)->tag, NULL, NULL);
 #ifdef __FreeBSD__
 			pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
-			    &src->addr,
 #else
-			pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
+			pf_send_tcp((*state)->rule.ptr, pd->af,
 #endif
-			    &dst->addr, src->port, dst->port,
+			    &sk->addr[pd->sidx], &sk->addr[pd->didx],
+			    sk->port[pd->sidx], sk->port[pd->didx],
 			    (*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
 			    TH_ACK, (*state)->dst.max_win, 0, 0, 1,
 			    0, NULL, NULL);
@@ -5259,7 +4721,11 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
 	if (((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) &&
 	    dst->state >= TCPS_FIN_WAIT_2 &&
 	    src->state >= TCPS_FIN_WAIT_2) {
+#ifdef __FreeBSD__
+		if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 		if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 			printf("pf: state reuse ");
 			pf_print_state(*state);
 			pf_print_flags(th->th_flags);
@@ -5282,21 +4748,31 @@ pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
 	}
 
 	/* translate source/destination address, if necessary */
-	if (STATE_TRANSLATE(*state)) {
-		if (direction == PF_OUT)
+	if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+		struct pf_state_key *nk = (*state)->key[pd->didx];
+
+		if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
+		    nk->port[pd->sidx] != th->th_sport)
 			pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
-			    &th->th_sum, &(*state)->gwy.addr,
-			    (*state)->gwy.port, 0, pd->af);
-		else
+			    &th->th_sum, &nk->addr[pd->sidx],
+			    nk->port[pd->sidx], 0, pd->af);
+
+		if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
+		    nk->port[pd->didx] != th->th_dport)
 			pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
-			    &th->th_sum, &(*state)->lan.addr,
-			    (*state)->lan.port, 0, pd->af);
-		m_copyback(m, off, sizeof(*th), (caddr_t)th);
-	} else if (copyback) {
-		/* Copyback sequence modulation or stateful scrub changes */
-		m_copyback(m, off, sizeof(*th), (caddr_t)th);
+			    &th->th_sum, &nk->addr[pd->didx],
+			    nk->port[pd->didx], 0, pd->af);
+		copyback = 1;
 	}
 
+	/* Copyback sequence modulation or stateful scrub changes if needed */
+	if (copyback)
+#ifdef __FreeBSD__
+		m_copyback(m, off, sizeof(*th), (caddr_t)th);
+#else
+		m_copyback(m, off, sizeof(*th), th);
+#endif
+
 	return (PF_PASS);
 }
 
@@ -5305,24 +4781,28 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
     struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
 {
 	struct pf_state_peer	*src, *dst;
-	struct pf_state_cmp	 key;
+	struct pf_state_key_cmp	 key;
 	struct udphdr		*uh = pd->hdr.udp;
 
 	key.af = pd->af;
 	key.proto = IPPROTO_UDP;
-	if (direction == PF_IN)	{
-		PF_ACPY(&key.ext.addr, pd->src, key.af);
-		PF_ACPY(&key.gwy.addr, pd->dst, key.af);
-		key.ext.port = uh->uh_sport;
-		key.gwy.port = uh->uh_dport;
-	} else {
-		PF_ACPY(&key.lan.addr, pd->src, key.af);
-		PF_ACPY(&key.ext.addr, pd->dst, key.af);
-		key.lan.port = uh->uh_sport;
-		key.ext.port = uh->uh_dport;
+	if (direction == PF_IN)	{	/* wire side, straight */
+		PF_ACPY(&key.addr[0], pd->src, key.af);
+		PF_ACPY(&key.addr[1], pd->dst, key.af);
+		key.port[0] = uh->uh_sport;
+		key.port[1] = uh->uh_dport;
+	} else {			/* stack side, reverse */
+		PF_ACPY(&key.addr[1], pd->src, key.af);
+		PF_ACPY(&key.addr[0], pd->dst, key.af);
+		key.port[1] = uh->uh_sport;
+		key.port[0] = uh->uh_dport;
 	}
 
-	STATE_LOOKUP();
+#ifdef __FreeBSD__
+	STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+	STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
 	if (direction == (*state)->direction) {
 		src = &(*state)->src;
@@ -5346,16 +4826,25 @@ pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
 		(*state)->timeout = PFTM_UDP_SINGLE;
 
 	/* translate source/destination address, if necessary */
-	if (STATE_TRANSLATE(*state)) {
-		if (direction == PF_OUT)
+	if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+		struct pf_state_key *nk = (*state)->key[pd->didx];
+
+		if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], pd->af) ||
+		    nk->port[pd->sidx] != uh->uh_sport)
 			pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
-			    &uh->uh_sum, &(*state)->gwy.addr,
-			    (*state)->gwy.port, 1, pd->af);
-		else
+			    &uh->uh_sum, &nk->addr[pd->sidx],
+			    nk->port[pd->sidx], 1, pd->af);
+
+		if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], pd->af) ||
+		    nk->port[pd->didx] != uh->uh_dport)
 			pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
-			    &uh->uh_sum, &(*state)->lan.addr,
-			    (*state)->lan.port, 1, pd->af);
+			    &uh->uh_sum, &nk->addr[pd->didx],
+			    nk->port[pd->didx], 1, pd->af);
+#ifdef __FreeBSD__
 		m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
+#else
+		m_copyback(m, off, sizeof(*uh), uh);
+#endif
 	}
 
 	return (PF_PASS);
@@ -5365,12 +4854,15 @@ int
 pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
     struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason)
 {
-	struct pf_addr	*saddr = pd->src, *daddr = pd->dst;
-	u_int16_t	 icmpid = 0;		/* make the compiler happy */
-	u_int16_t	*icmpsum = NULL;	/* make the compiler happy */
-	u_int8_t	 icmptype = 0;		/* make the compiler happy */
+	struct pf_addr  *saddr = pd->src, *daddr = pd->dst;
+#ifdef __FreeBSD__
+	u_int16_t	 icmpid = 0, *icmpsum;
+#else
+	u_int16_t	 icmpid, *icmpsum;
+#endif
+	u_int8_t	 icmptype;
 	int		 state_icmp = 0;
-	struct pf_state_cmp key;
+	struct pf_state_key_cmp key;
 
 	switch (pd->proto) {
 #ifdef INET
@@ -5410,84 +4902,84 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 		 */
 		key.af = pd->af;
 		key.proto = pd->proto;
-		if (direction == PF_IN)	{
-			PF_ACPY(&key.ext.addr, pd->src, key.af);
-			PF_ACPY(&key.gwy.addr, pd->dst, key.af);
-			key.ext.port = 0;
-			key.gwy.port = icmpid;
-		} else {
-			PF_ACPY(&key.lan.addr, pd->src, key.af);
-			PF_ACPY(&key.ext.addr, pd->dst, key.af);
-			key.lan.port = icmpid;
-			key.ext.port = 0;
+		key.port[0] = key.port[1] = icmpid;
+		if (direction == PF_IN)	{	/* wire side, straight */
+			PF_ACPY(&key.addr[0], pd->src, key.af);
+			PF_ACPY(&key.addr[1], pd->dst, key.af);
+		} else {			/* stack side, reverse */
+			PF_ACPY(&key.addr[1], pd->src, key.af);
+			PF_ACPY(&key.addr[0], pd->dst, key.af);
 		}
 
-		STATE_LOOKUP();
+#ifdef __FreeBSD__
+		STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+		STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
 		(*state)->expire = time_second;
 		(*state)->timeout = PFTM_ICMP_ERROR_REPLY;
 
 		/* translate source/destination address, if necessary */
-		if (STATE_TRANSLATE(*state)) {
-			if (direction == PF_OUT) {
-				switch (pd->af) {
-#ifdef INET
-				case AF_INET:
-					pf_change_a(&saddr->v4.s_addr,
-					    pd->ip_sum,
-					    (*state)->gwy.addr.v4.s_addr, 0);
-					pd->hdr.icmp->icmp_cksum =
-					    pf_cksum_fixup(
-					    pd->hdr.icmp->icmp_cksum, icmpid,
-					    (*state)->gwy.port, 0);
-					pd->hdr.icmp->icmp_id =
-					    (*state)->gwy.port;
-					m_copyback(m, off, ICMP_MINLEN,
-					    (caddr_t)pd->hdr.icmp);
-					break;
-#endif /* INET */
-#ifdef INET6
-				case AF_INET6:
-					pf_change_a6(saddr,
-					    &pd->hdr.icmp6->icmp6_cksum,
-					    &(*state)->gwy.addr, 0);
-					m_copyback(m, off,
-					    sizeof(struct icmp6_hdr),
-					    (caddr_t)pd->hdr.icmp6);
-					break;
-#endif /* INET6 */
-				}
-			} else {
-				switch (pd->af) {
+		if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+			struct pf_state_key *nk = (*state)->key[pd->didx];
+
+			switch (pd->af) {
 #ifdef INET
-				case AF_INET:
+			case AF_INET:
+				if (PF_ANEQ(pd->src,
+				    &nk->addr[pd->sidx], AF_INET))
+					pf_change_a(&saddr->v4.s_addr,
+					    pd->ip_sum,
+					    nk->addr[pd->sidx].v4.s_addr, 0);
+
+				if (PF_ANEQ(pd->dst, &nk->addr[pd->didx],
+				    AF_INET))
 					pf_change_a(&daddr->v4.s_addr,
 					    pd->ip_sum,
-					    (*state)->lan.addr.v4.s_addr, 0);
+					    nk->addr[pd->didx].v4.s_addr, 0);
+
+				if (nk->port[0] !=
+				    pd->hdr.icmp->icmp_id) {
 					pd->hdr.icmp->icmp_cksum =
 					    pf_cksum_fixup(
 					    pd->hdr.icmp->icmp_cksum, icmpid,
-					    (*state)->lan.port, 0);
+					    nk->port[pd->sidx], 0);
 					pd->hdr.icmp->icmp_id =
-					    (*state)->lan.port;
-					m_copyback(m, off, ICMP_MINLEN,
-					    (caddr_t)pd->hdr.icmp);
-					break;
+					    nk->port[pd->sidx];
+				}
+
+				m_copyback(m, off, ICMP_MINLEN,
+#ifdef __FreeBSD__
+				    (caddr_t)
+#endif
+				    pd->hdr.icmp);
+				break;
 #endif /* INET */
 #ifdef INET6
-				case AF_INET6:
+			case AF_INET6:
+				if (PF_ANEQ(pd->src,
+				    &nk->addr[pd->sidx], AF_INET6))
+					pf_change_a6(saddr,
+					    &pd->hdr.icmp6->icmp6_cksum,
+					    &nk->addr[pd->sidx], 0);
+
+				if (PF_ANEQ(pd->dst,
+				    &nk->addr[pd->didx], AF_INET6))
 					pf_change_a6(daddr,
 					    &pd->hdr.icmp6->icmp6_cksum,
-					    &(*state)->lan.addr, 0);
-					m_copyback(m, off,
-					    sizeof(struct icmp6_hdr),
-					    (caddr_t)pd->hdr.icmp6);
-					break;
+					    &nk->addr[pd->didx], 0);
+
+				m_copyback(m, off,
+				    sizeof(struct icmp6_hdr),
+#ifdef __FreeBSD__
+				    (caddr_t)
+#endif
+				    pd->hdr.icmp6);
+				break;
 #endif /* INET6 */
-				}
 			}
 		}
-
 		return (PF_PASS);
 
 	} else {
@@ -5497,6 +4989,9 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 		 */
 
 		struct pf_pdesc	pd2;
+#ifdef __FreeBSD__
+		bzero(&pd2, sizeof pd2);
+#endif
 #ifdef INET
 		struct ip	h2;
 #endif /* INET */
@@ -5504,10 +4999,18 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 		struct ip6_hdr	h2_6;
 		int		terminal = 0;
 #endif /* INET6 */
-		int		ipoff2 = 0;	/* make the compiler happy */
-		int		off2 = 0;	/* make the compiler happy */
+#ifdef __FreeBSD__
+		int		ipoff2 = 0;
+		int		off2 = 0;
+#else
+		int		ipoff2;
+		int		off2;
+#endif
 
 		pd2.af = pd->af;
+		/* Payload packet is from the opposite direction. */
+		pd2.sidx = (direction == PF_IN) ? 1 : 0;
+		pd2.didx = (direction == PF_IN) ? 0 : 1;
 		switch (pd->af) {
 #ifdef INET
 		case AF_INET:
@@ -5593,10 +5096,6 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 			} while (!terminal);
 			break;
 #endif /* INET6 */
-#ifdef __FreeBSD__
-		default:
-			panic("AF not supported: %d", pd->af);
-#endif
 		}
 
 		switch (pd2.proto) {
@@ -5622,19 +5121,16 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 
 			key.af = pd2.af;
 			key.proto = IPPROTO_TCP;
-			if (direction == PF_IN)	{
-				PF_ACPY(&key.ext.addr, pd2.dst, key.af);
-				PF_ACPY(&key.gwy.addr, pd2.src, key.af);
-				key.ext.port = th.th_dport;
-				key.gwy.port = th.th_sport;
-			} else {
-				PF_ACPY(&key.lan.addr, pd2.dst, key.af);
-				PF_ACPY(&key.ext.addr, pd2.src, key.af);
-				key.lan.port = th.th_dport;
-				key.ext.port = th.th_sport;
-			}
+			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+			key.port[pd2.sidx] = th.th_sport;
+			key.port[pd2.didx] = th.th_dport;
 
-			STATE_LOOKUP();
+#ifdef __FreeBSD__
+			STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+			STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
 			if (direction == (*state)->direction) {
 				src = &(*state)->dst;
@@ -5660,7 +5156,11 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 			if (!((*state)->state_flags & PFSTATE_SLOPPY) &&
 			    (!SEQ_GEQ(src->seqhi, seq) ||
 			    !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)))) {
+#ifdef __FreeBSD__
+				if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 				if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 					printf("pf: BAD ICMP %d:%d ",
 					    icmptype, pd->hdr.icmp->icmp_code);
 					pf_print_host(pd->src, 0, pd->af);
@@ -5672,22 +5172,47 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 				}
 				REASON_SET(reason, PFRES_BADSTATE);
 				return (PF_DROP);
+			} else {
+#ifdef __FreeBSD__
+				if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+				if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
+					printf("pf: OK ICMP %d:%d ",
+					    icmptype, pd->hdr.icmp->icmp_code);
+					pf_print_host(pd->src, 0, pd->af);
+					printf(" -> ");
+					pf_print_host(pd->dst, 0, pd->af);
+					printf(" state: ");
+					pf_print_state(*state);
+					printf(" seq=%u\n", seq);
+				}
 			}
 
-			if (STATE_TRANSLATE(*state)) {
-				if (direction == PF_IN) {
+			/* translate source/destination address, if necessary */
+			if ((*state)->key[PF_SK_WIRE] !=
+			    (*state)->key[PF_SK_STACK]) {
+				struct pf_state_key *nk =
+				    (*state)->key[pd->didx];
+
+				if (PF_ANEQ(pd2.src,
+				    &nk->addr[pd2.sidx], pd2.af) ||
+				    nk->port[pd2.sidx] != th.th_sport)
 					pf_change_icmp(pd2.src, &th.th_sport,
-					    daddr, &(*state)->lan.addr,
-					    (*state)->lan.port, NULL,
+					    daddr, &nk->addr[pd2.sidx],
+					    nk->port[pd2.sidx], NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, pd2.af);
-				} else {
+
+				if (PF_ANEQ(pd2.dst,
+				    &nk->addr[pd2.didx], pd2.af) ||
+				    nk->port[pd2.didx] != th.th_dport)
 					pf_change_icmp(pd2.dst, &th.th_dport,
-					    saddr, &(*state)->gwy.addr,
-					    (*state)->gwy.port, NULL,
+					    NULL, /* XXX Inbound NAT? */
+					    &nk->addr[pd2.didx],
+					    nk->port[pd2.didx], NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, pd2.af);
-				}
 				copyback = 1;
 			}
 
@@ -5696,22 +5221,38 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 #ifdef INET
 				case AF_INET:
 					m_copyback(m, off, ICMP_MINLEN,
-					    (caddr_t)pd->hdr.icmp);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    pd->hdr.icmp);
 					m_copyback(m, ipoff2, sizeof(h2),
-					    (caddr_t)&h2);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    &h2);
 					break;
 #endif /* INET */
 #ifdef INET6
 				case AF_INET6:
 					m_copyback(m, off,
 					    sizeof(struct icmp6_hdr),
-					    (caddr_t)pd->hdr.icmp6);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    pd->hdr.icmp6);
 					m_copyback(m, ipoff2, sizeof(h2_6),
-					    (caddr_t)&h2_6);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    &h2_6);
 					break;
 #endif /* INET6 */
 				}
+#ifdef __FreeBSD__
 				m_copyback(m, off2, 8, (caddr_t)&th);
+#else
+				m_copyback(m, off2, 8, &th);
+#endif
 			}
 
 			return (PF_PASS);
@@ -5730,57 +5271,79 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 
 			key.af = pd2.af;
 			key.proto = IPPROTO_UDP;
-			if (direction == PF_IN)	{
-				PF_ACPY(&key.ext.addr, pd2.dst, key.af);
-				PF_ACPY(&key.gwy.addr, pd2.src, key.af);
-				key.ext.port = uh.uh_dport;
-				key.gwy.port = uh.uh_sport;
-			} else {
-				PF_ACPY(&key.lan.addr, pd2.dst, key.af);
-				PF_ACPY(&key.ext.addr, pd2.src, key.af);
-				key.lan.port = uh.uh_dport;
-				key.ext.port = uh.uh_sport;
-			}
+			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+			key.port[pd2.sidx] = uh.uh_sport;
+			key.port[pd2.didx] = uh.uh_dport;
+
+#ifdef __FreeBSD__
+			STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+			STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
-			STATE_LOOKUP();
+			/* translate source/destination address, if necessary */
+			if ((*state)->key[PF_SK_WIRE] !=
+			    (*state)->key[PF_SK_STACK]) {
+				struct pf_state_key *nk =
+				    (*state)->key[pd->didx];
 
-			if (STATE_TRANSLATE(*state)) {
-				if (direction == PF_IN) {
+				if (PF_ANEQ(pd2.src,
+				    &nk->addr[pd2.sidx], pd2.af) ||
+				    nk->port[pd2.sidx] != uh.uh_sport)
 					pf_change_icmp(pd2.src, &uh.uh_sport,
-					    daddr, &(*state)->lan.addr,
-					    (*state)->lan.port, &uh.uh_sum,
+					    daddr, &nk->addr[pd2.sidx],
+					    nk->port[pd2.sidx], &uh.uh_sum,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 1, pd2.af);
-				} else {
+
+				if (PF_ANEQ(pd2.dst,
+				    &nk->addr[pd2.didx], pd2.af) ||
+				    nk->port[pd2.didx] != uh.uh_dport)
 					pf_change_icmp(pd2.dst, &uh.uh_dport,
-					    saddr, &(*state)->gwy.addr,
-					    (*state)->gwy.port, &uh.uh_sum,
+					    NULL, /* XXX Inbound NAT? */
+					    &nk->addr[pd2.didx],
+					    nk->port[pd2.didx], &uh.uh_sum,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 1, pd2.af);
-				}
+
 				switch (pd2.af) {
 #ifdef INET
 				case AF_INET:
 					m_copyback(m, off, ICMP_MINLEN,
-					    (caddr_t)pd->hdr.icmp);
-					m_copyback(m, ipoff2, sizeof(h2),
-					    (caddr_t)&h2);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    pd->hdr.icmp);
+#ifdef __FreeBSD__
+					m_copyback(m, ipoff2, sizeof(h2), (caddr_t)&h2);
+#else
+					m_copyback(m, ipoff2, sizeof(h2), &h2);
+#endif
 					break;
 #endif /* INET */
 #ifdef INET6
 				case AF_INET6:
 					m_copyback(m, off,
 					    sizeof(struct icmp6_hdr),
-					    (caddr_t)pd->hdr.icmp6);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    pd->hdr.icmp6);
 					m_copyback(m, ipoff2, sizeof(h2_6),
-					    (caddr_t)&h2_6);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    &h2_6);
 					break;
 #endif /* INET6 */
 				}
-				m_copyback(m, off2, sizeof(uh),
-				    (caddr_t)&uh);
+#ifdef __FreeBSD__
+				m_copyback(m, off2, sizeof(uh), (caddr_t)&uh);
+#else
+				m_copyback(m, off2, sizeof(uh), &uh);
+#endif
 			}
-
 			return (PF_PASS);
 			break;
 		}
@@ -5798,42 +5361,51 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 
 			key.af = pd2.af;
 			key.proto = IPPROTO_ICMP;
-			if (direction == PF_IN)	{
-				PF_ACPY(&key.ext.addr, pd2.dst, key.af);
-				PF_ACPY(&key.gwy.addr, pd2.src, key.af);
-				key.ext.port = 0;
-				key.gwy.port = iih.icmp_id;
-			} else {
-				PF_ACPY(&key.lan.addr, pd2.dst, key.af);
-				PF_ACPY(&key.ext.addr, pd2.src, key.af);
-				key.lan.port = iih.icmp_id;
-				key.ext.port = 0;
-			}
+			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+			key.port[0] = key.port[1] = iih.icmp_id;
+
+#ifdef __FreeBSD__
+			STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+			STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
-			STATE_LOOKUP();
+			/* translate source/destination address, if necessary */
+			if ((*state)->key[PF_SK_WIRE] !=
+			    (*state)->key[PF_SK_STACK]) {
+				struct pf_state_key *nk =
+				    (*state)->key[pd->didx];
 
-			if (STATE_TRANSLATE(*state)) {
-				if (direction == PF_IN) {
+				if (PF_ANEQ(pd2.src,
+				    &nk->addr[pd2.sidx], pd2.af) ||
+				    nk->port[pd2.sidx] != iih.icmp_id)
 					pf_change_icmp(pd2.src, &iih.icmp_id,
-					    daddr, &(*state)->lan.addr,
-					    (*state)->lan.port, NULL,
+					    daddr, &nk->addr[pd2.sidx],
+					    nk->port[pd2.sidx], NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, AF_INET);
-				} else {
+
+				if (PF_ANEQ(pd2.dst,
+				    &nk->addr[pd2.didx], pd2.af) ||
+				    nk->port[pd2.didx] != iih.icmp_id)
 					pf_change_icmp(pd2.dst, &iih.icmp_id,
-					    saddr, &(*state)->gwy.addr,
-					    (*state)->gwy.port, NULL,
+					    NULL, /* XXX Inbound NAT? */
+					    &nk->addr[pd2.didx],
+					    nk->port[pd2.didx], NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, AF_INET);
-				}
-				m_copyback(m, off, ICMP_MINLEN,
-				    (caddr_t)pd->hdr.icmp);
-				m_copyback(m, ipoff2, sizeof(h2),
-				    (caddr_t)&h2);
-				m_copyback(m, off2, ICMP_MINLEN,
-				    (caddr_t)&iih);
-			}
 
+#ifdef __FreeBSD__
+				m_copyback(m, off, ICMP_MINLEN, (caddr_t)pd->hdr.icmp);
+				m_copyback(m, ipoff2, sizeof(h2), (caddr_t)&h2);
+				m_copyback(m, off2, ICMP_MINLEN, (caddr_t)&iih);
+#else
+				m_copyback(m, off, ICMP_MINLEN, pd->hdr.icmp);
+				m_copyback(m, ipoff2, sizeof(h2), &h2);
+				m_copyback(m, off2, ICMP_MINLEN, &iih);
+#endif
+			}
 			return (PF_PASS);
 			break;
 		}
@@ -5852,42 +5424,55 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 
 			key.af = pd2.af;
 			key.proto = IPPROTO_ICMPV6;
-			if (direction == PF_IN)	{
-				PF_ACPY(&key.ext.addr, pd2.dst, key.af);
-				PF_ACPY(&key.gwy.addr, pd2.src, key.af);
-				key.ext.port = 0;
-				key.gwy.port = iih.icmp6_id;
-			} else {
-				PF_ACPY(&key.lan.addr, pd2.dst, key.af);
-				PF_ACPY(&key.ext.addr, pd2.src, key.af);
-				key.lan.port = iih.icmp6_id;
-				key.ext.port = 0;
-			}
+			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+			key.port[0] = key.port[1] = iih.icmp6_id;
+
+#ifdef __FreeBSD__
+			STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+			STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
-			STATE_LOOKUP();
+			/* translate source/destination address, if necessary */
+			if ((*state)->key[PF_SK_WIRE] !=
+			    (*state)->key[PF_SK_STACK]) {
+				struct pf_state_key *nk =
+				    (*state)->key[pd->didx];
 
-			if (STATE_TRANSLATE(*state)) {
-				if (direction == PF_IN) {
+				if (PF_ANEQ(pd2.src,
+				    &nk->addr[pd2.sidx], pd2.af) ||
+				    nk->port[pd2.sidx] != iih.icmp6_id)
 					pf_change_icmp(pd2.src, &iih.icmp6_id,
-					    daddr, &(*state)->lan.addr,
-					    (*state)->lan.port, NULL,
+					    daddr, &nk->addr[pd2.sidx],
+					    nk->port[pd2.sidx], NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, AF_INET6);
-				} else {
+
+				if (PF_ANEQ(pd2.dst,
+				    &nk->addr[pd2.didx], pd2.af) ||
+				    nk->port[pd2.didx] != iih.icmp6_id)
 					pf_change_icmp(pd2.dst, &iih.icmp6_id,
-					    saddr, &(*state)->gwy.addr,
-					    (*state)->gwy.port, NULL,
+					    NULL, /* XXX Inbound NAT? */
+					    &nk->addr[pd2.didx],
+					    nk->port[pd2.didx], NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, AF_INET6);
-				}
+
+#ifdef __FreeBSD__
 				m_copyback(m, off, sizeof(struct icmp6_hdr),
 				    (caddr_t)pd->hdr.icmp6);
-				m_copyback(m, ipoff2, sizeof(h2_6),
-				    (caddr_t)&h2_6);
+				m_copyback(m, ipoff2, sizeof(h2_6), (caddr_t)&h2_6);
 				m_copyback(m, off2, sizeof(struct icmp6_hdr),
 				    (caddr_t)&iih);
+#else
+				m_copyback(m, off, sizeof(struct icmp6_hdr),
+				    pd->hdr.icmp6);
+				m_copyback(m, ipoff2, sizeof(h2_6), &h2_6);
+				m_copyback(m, off2, sizeof(struct icmp6_hdr),
+				    &iih);
+#endif
 			}
-
 			return (PF_PASS);
 			break;
 		}
@@ -5895,55 +5480,68 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 		default: {
 			key.af = pd2.af;
 			key.proto = pd2.proto;
-			if (direction == PF_IN)	{
-				PF_ACPY(&key.ext.addr, pd2.dst, key.af);
-				PF_ACPY(&key.gwy.addr, pd2.src, key.af);
-				key.ext.port = 0;
-				key.gwy.port = 0;
-			} else {
-				PF_ACPY(&key.lan.addr, pd2.dst, key.af);
-				PF_ACPY(&key.ext.addr, pd2.src, key.af);
-				key.lan.port = 0;
-				key.ext.port = 0;
-			}
+			PF_ACPY(&key.addr[pd2.sidx], pd2.src, key.af);
+			PF_ACPY(&key.addr[pd2.didx], pd2.dst, key.af);
+			key.port[0] = key.port[1] = 0;
+
+#ifdef __FreeBSD__
+			STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+			STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
-			STATE_LOOKUP();
+			/* translate source/destination address, if necessary */
+			if ((*state)->key[PF_SK_WIRE] !=
+			    (*state)->key[PF_SK_STACK]) {
+				struct pf_state_key *nk =
+				    (*state)->key[pd->didx];
 
-			if (STATE_TRANSLATE(*state)) {
-				if (direction == PF_IN) {
-					pf_change_icmp(pd2.src, NULL,
-					    daddr, &(*state)->lan.addr,
-					    0, NULL,
+				if (PF_ANEQ(pd2.src,
+				    &nk->addr[pd2.sidx], pd2.af))
+					pf_change_icmp(pd2.src, NULL, daddr,
+					    &nk->addr[pd2.sidx], 0, NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, pd2.af);
-				} else {
-					pf_change_icmp(pd2.dst, NULL,
-					    saddr, &(*state)->gwy.addr,
-					    0, NULL,
+
+				if (PF_ANEQ(pd2.dst,
+				    &nk->addr[pd2.didx], pd2.af))
+					pf_change_icmp(pd2.src, NULL,
+					    NULL, /* XXX Inbound NAT? */
+					    &nk->addr[pd2.didx], 0, NULL,
 					    pd2.ip_sum, icmpsum,
 					    pd->ip_sum, 0, pd2.af);
-				}
+
 				switch (pd2.af) {
 #ifdef INET
 				case AF_INET:
+#ifdef __FreeBSD__
 					m_copyback(m, off, ICMP_MINLEN,
 					    (caddr_t)pd->hdr.icmp);
-					m_copyback(m, ipoff2, sizeof(h2),
-					    (caddr_t)&h2);
+					m_copyback(m, ipoff2, sizeof(h2), (caddr_t)&h2);
+#else
+					m_copyback(m, off, ICMP_MINLEN,
+					    pd->hdr.icmp);
+					m_copyback(m, ipoff2, sizeof(h2), &h2);
+#endif
 					break;
 #endif /* INET */
 #ifdef INET6
 				case AF_INET6:
 					m_copyback(m, off,
 					    sizeof(struct icmp6_hdr),
-					    (caddr_t)pd->hdr.icmp6);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    pd->hdr.icmp6);
 					m_copyback(m, ipoff2, sizeof(h2_6),
-					    (caddr_t)&h2_6);
+#ifdef __FreeBSD__
+					    (caddr_t)
+#endif
+					    &h2_6);
 					break;
 #endif /* INET6 */
 				}
 			}
-
 			return (PF_PASS);
 			break;
 		}
@@ -5953,26 +5551,28 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
 
 int
 pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
-    struct pf_pdesc *pd)
+    struct mbuf *m, struct pf_pdesc *pd)
 {
 	struct pf_state_peer	*src, *dst;
-	struct pf_state_cmp	 key;
+	struct pf_state_key_cmp	 key;
 
 	key.af = pd->af;
 	key.proto = pd->proto;
 	if (direction == PF_IN)	{
-		PF_ACPY(&key.ext.addr, pd->src, key.af);
-		PF_ACPY(&key.gwy.addr, pd->dst, key.af);
-		key.ext.port = 0;
-		key.gwy.port = 0;
+		PF_ACPY(&key.addr[0], pd->src, key.af);
+		PF_ACPY(&key.addr[1], pd->dst, key.af);
+		key.port[0] = key.port[1] = 0;
 	} else {
-		PF_ACPY(&key.lan.addr, pd->src, key.af);
-		PF_ACPY(&key.ext.addr, pd->dst, key.af);
-		key.lan.port = 0;
-		key.ext.port = 0;
+		PF_ACPY(&key.addr[1], pd->src, key.af);
+		PF_ACPY(&key.addr[0], pd->dst, key.af);
+		key.port[1] = key.port[0] = 0;
 	}
 
-	STATE_LOOKUP();
+#ifdef __FreeBSD__
+	STATE_LOOKUP(kif, &key, direction, *state, m, pd->pf_mtag);
+#else
+	STATE_LOOKUP(kif, &key, direction, *state, m);
+#endif
 
 	if (direction == (*state)->direction) {
 		src = &(*state)->src;
@@ -5996,39 +5596,48 @@ pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
 		(*state)->timeout = PFTM_OTHER_SINGLE;
 
 	/* translate source/destination address, if necessary */
-	if (STATE_TRANSLATE(*state)) {
-		if (direction == PF_OUT)
-			switch (pd->af) {
+	if ((*state)->key[PF_SK_WIRE] != (*state)->key[PF_SK_STACK]) {
+		struct pf_state_key *nk = (*state)->key[pd->didx];
+
+#ifdef __FreeBSD__
+		KASSERT(nk, ("%s: nk is null", __FUNCTION__));
+		KASSERT(pd, ("%s: pd is null", __FUNCTION__));
+		KASSERT(pd->src, ("%s: pd->src is null", __FUNCTION__));
+		KASSERT(pd->dst, ("%s: pd->dst is null", __FUNCTION__));
+#else
+		KASSERT(nk);
+		KASSERT(pd);
+		KASSERT(pd->src);
+		KASSERT(pd->dst);
+#endif
+		switch (pd->af) {
 #ifdef INET
-			case AF_INET:
+		case AF_INET:
+			if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET))
 				pf_change_a(&pd->src->v4.s_addr,
-				    pd->ip_sum, (*state)->gwy.addr.v4.s_addr,
+				    pd->ip_sum,
+				    nk->addr[pd->sidx].v4.s_addr,
 				    0);
-				break;
-#endif /* INET */
-#ifdef INET6
-			case AF_INET6:
-				PF_ACPY(pd->src, &(*state)->gwy.addr, pd->af);
-				break;
-#endif /* INET6 */
-			}
-		else
-			switch (pd->af) {
-#ifdef INET
-			case AF_INET:
+
+
+			if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET))
 				pf_change_a(&pd->dst->v4.s_addr,
-				    pd->ip_sum, (*state)->lan.addr.v4.s_addr,
+				    pd->ip_sum,
+				    nk->addr[pd->didx].v4.s_addr,
 				    0);
+
 				break;
 #endif /* INET */
 #ifdef INET6
-			case AF_INET6:
-				PF_ACPY(pd->dst, &(*state)->lan.addr, pd->af);
-				break;
+		case AF_INET6:
+			if (PF_ANEQ(pd->src, &nk->addr[pd->sidx], AF_INET))
+				PF_ACPY(pd->src, &nk->addr[pd->sidx], pd->af);
+
+			if (PF_ANEQ(pd->dst, &nk->addr[pd->didx], AF_INET))
+				PF_ACPY(pd->dst, &nk->addr[pd->didx], pd->af);
 #endif /* INET6 */
-			}
+		}
 	}
-
 	return (PF_PASS);
 }
 
@@ -6086,6 +5695,11 @@ pf_pull_hdr(struct mbuf *m, int off, void *p, int len,
 int
 pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
 {
+#ifdef __FreeBSD__
+#ifdef RADIX_MPATH
+	struct radix_node_head	*rnh;
+#endif
+#endif
 	struct sockaddr_in	*dst;
 	int			 ret = 1;
 	int			 check_mpath;
@@ -6106,6 +5720,14 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
 	struct ifnet		*ifp;
 
 	check_mpath = 0;
+#ifdef __FreeBSD__
+#ifdef RADIX_MPATH
+	/* XXX: stick to table 0 for now */
+	rnh = rt_tables_get_rnh(0, af);
+	if (rnh != NULL && rn_mpath_capable(rnh))
+		check_mpath = 1;
+#endif
+#endif
 	bzero(&ro, sizeof(ro));
 	switch (af) {
 	case AF_INET:
@@ -6113,18 +5735,24 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
 		dst->sin_family = AF_INET;
 		dst->sin_len = sizeof(*dst);
 		dst->sin_addr = addr->v4;
-#ifndef __FreeBSD__	/* MULTIPATH_ROUTING */
+#ifndef __FreeBSD__
 		if (ipmultipath)
 			check_mpath = 1;
 #endif
 		break;
 #ifdef INET6
 	case AF_INET6:
+		/*
+		 * Skip check for addresses with embedded interface scope,
+		 * as they would always match anyway.
+		 */
+		if (IN6_IS_SCOPE_EMBED(&addr->v6))
+			goto out;
 		dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
 		dst6->sin6_family = AF_INET6;
 		dst6->sin6_len = sizeof(*dst6);
 		dst6->sin6_addr = addr->v6;
-#ifndef __FreeBSD__	/* MULTIPATH_ROUTING */
+#ifndef __FreeBSD__
 		if (ip6_multipath)
 			check_mpath = 1;
 #endif
@@ -6174,11 +5802,13 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
 
 			if (kif->pfik_ifp == ifp)
 				ret = 1;
-#ifdef __FreeBSD__ /* MULTIPATH_ROUTING */
-			rn = NULL;
-#else
+#ifdef __FreeBSD__
+#ifdef RADIX_MPATH
 			rn = rn_mpath_next(rn);
 #endif
+#else
+			rn = rn_mpath_next(rn, 0);
+#endif
 		} while (check_mpath == 1 && rn != NULL && ret == 0);
 	} else
 		ret = 0;
@@ -6249,7 +5879,6 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
 }
 
 #ifdef INET
-
 void
 pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
     struct pf_state *s, struct pf_pdesc *pd)
@@ -6274,7 +5903,11 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 	    (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
 		panic("pf_route: invalid parameters");
 
+#ifdef __FreeBSD__
 	if (pd->pf_mtag->routed++ > 3) {
+#else
+	if ((*m)->m_pkthdr.pf.routed++ > 3) {
+#endif
 		m0 = *m;
 		*m = NULL;
 		goto bad;
@@ -6309,9 +5942,17 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 	dst->sin_addr = ip->ip_dst;
 
 	if (r->rt == PF_FASTROUTE) {
+#ifdef __FreeBSD__
 		in_rtalloc(ro, 0);
+#else
+		rtalloc(ro);
+#endif
 		if (ro->ro_rt == 0) {
+#ifdef __FreeBSD__
 			KMOD_IPSTAT_INC(ips_noroute);
+#else
+			ipstat.ips_noroute++;
+#endif
 			goto bad;
 		}
 
@@ -6377,7 +6018,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 		 * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least)
 		 */
 		NTOHS(ip->ip_len);
-		NTOHS(ip->ip_off);	 /* XXX: needed? */
+		NTOHS(ip->ip_off);	/* XXX: needed? */
 		in_delayed_cksum(m0);
 		HTONS(ip->ip_len);
 		HTONS(ip->ip_off);
@@ -6386,9 +6027,8 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 	m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
 
 	if (ntohs(ip->ip_len) <= ifp->if_mtu ||
-	    (m0->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 ||
 	    (ifp->if_hwassist & CSUM_FRAGMENT &&
-		((ip->ip_off & htons(IP_DF)) == 0))) {
+	    ((ip->ip_off & htons(IP_DF)) == 0))) {
 		/*
 		 * ip->ip_len = htons(ip->ip_len);
 		 * ip->ip_off = htons(ip->ip_off);
@@ -6408,7 +6048,6 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 		PF_LOCK();
 		goto done;
 	}
-
 #else
 	/* Copied from ip_output. */
 #ifdef IPSEC
@@ -6429,25 +6068,28 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 		if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
 		    ifp->if_bridge != NULL) {
 			in_delayed_cksum(m0);
-			m0->m_pkthdr.csum_flags &= ~M_TCPV4_CSUM_OUT; /* Clear */
+			m0->m_pkthdr.csum_flags &= ~M_TCPV4_CSUM_OUT; /* Clr */
 		}
 	} else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) {
 		if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
 		    ifp->if_bridge != NULL) {
 			in_delayed_cksum(m0);
-			m0->m_pkthdr.csum_flags &= ~M_UDPV4_CSUM_OUT; /* Clear */
+			m0->m_pkthdr.csum_flags &= ~M_UDPV4_CSUM_OUT; /* Clr */
 		}
 	}
 
 	if (ntohs(ip->ip_len) <= ifp->if_mtu) {
+		ip->ip_sum = 0;
 		if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
 		    ifp->if_bridge == NULL) {
 			m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
+#ifdef __FreeBSD__
 			KMOD_IPSTAT_INC(ips_outhwcsum);
-		} else {
-			ip->ip_sum = 0;
+#else
+			ipstat.ips_outhwcsum++;
+#endif
+		} else
 			ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
-		}
 		/* Update relevant hardware checksum stats for TCP/UDP */
 		if (m0->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
 			KMOD_TCPSTAT_INC(tcps_outhwcsum);
@@ -6457,12 +6099,17 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 		goto done;
 	}
 #endif
+
 	/*
 	 * Too large for interface; fragment if possible.
 	 * Must be able to put at least 8 bytes per fragment.
 	 */
-	if (ip->ip_off & htons(IP_DF) || (m0->m_pkthdr.csum_flags & CSUM_TSO)) {
+	if (ip->ip_off & htons(IP_DF)) {
+#ifdef __FreeBSD__
 		KMOD_IPSTAT_INC(ips_cantfrag);
+#else
+		ipstat.ips_cantfrag++;
+#endif
 		if (r->rt != PF_DUPTO) {
 #ifdef __FreeBSD__
 			/* icmp_error() expects host byte ordering */
@@ -6493,7 +6140,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 	error = ip_fragment(m0, ifp, ifp->if_mtu);
 #endif
 	if (error) {
-#ifndef __FreeBSD__	/* ip_fragment does not do m_freem() on FreeBSD */
+#ifndef __FreeBSD__    /* ip_fragment does not do m_freem() on FreeBSD */
 		m0 = NULL;
 #endif
 		goto bad;
@@ -6519,7 +6166,11 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 	}
 
 	if (error == 0)
+#ifdef __FreeBSD__
 		KMOD_IPSTAT_INC(ips_fragmented);
+#else
+		ipstat.ips_fragmented++;
+#endif
 
 done:
 	if (r->rt != PF_DUPTO)
@@ -6547,13 +6198,16 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 	struct ifnet		*ifp = NULL;
 	struct pf_addr		 naddr;
 	struct pf_src_node	*sn = NULL;
-	int			 error = 0;
 
 	if (m == NULL || *m == NULL || r == NULL ||
 	    (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
 		panic("pf_route6: invalid parameters");
 
+#ifdef __FreeBSD__
 	if (pd->pf_mtag->routed++ > 3) {
+#else
+	if ((*m)->m_pkthdr.pf.routed++ > 3) {
+#endif
 		m0 = *m;
 		*m = NULL;
 		goto bad;
@@ -6592,14 +6246,9 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 		m0->m_flags |= M_SKIP_FIREWALL;
 		PF_UNLOCK();
 		ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
-		PF_LOCK();
 #else
-		mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
-		if (mtag == NULL)
-			goto bad;
-		m_tag_prepend(m0, mtag);
-		pd->pf_mtag->flags |= PF_TAG_GENERATED;
-		ip6_output(m0, NULL, NULL, 0, NULL, NULL);
+		m0->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
+		ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
 #endif
 		return;
 	}
@@ -6660,7 +6309,7 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 #ifdef __FreeBSD__
 		PF_UNLOCK();
 #endif
-		error = nd6_output(ifp, ifp, m0, dst, NULL);
+		nd6_output(ifp, ifp, m0, dst, NULL);
 #ifdef __FreeBSD__
 		PF_LOCK();
 #endif
@@ -6671,7 +6320,7 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
 			PF_UNLOCK();
 			icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
 			PF_LOCK();
-		 } else
+		} else
 #else
 		if (r->rt != PF_DUPTO)
 			icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
@@ -6691,7 +6340,6 @@ bad:
 }
 #endif /* INET6 */
 
-
 #ifdef __FreeBSD__
 /*
  * FreeBSD supports cksum offloads for the following drivers.
@@ -6729,10 +6377,10 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t a
 			if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
 				sum = m->m_pkthdr.csum_data;
 			} else {
-				ip = mtod(m, struct ip *);	
+				ip = mtod(m, struct ip *);
 				sum = in_pseudo(ip->ip_src.s_addr,
-					ip->ip_dst.s_addr, htonl((u_short)len + 
-					m->m_pkthdr.csum_data + IPPROTO_TCP));
+				ip->ip_dst.s_addr, htonl((u_short)len + 
+				m->m_pkthdr.csum_data + IPPROTO_TCP));
 			}
 			sum ^= 0xffff;
 			++hw_assist;
@@ -6743,14 +6391,14 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t a
 			if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
 				sum = m->m_pkthdr.csum_data;
 			} else {
-				ip = mtod(m, struct ip *);	
+				ip = mtod(m, struct ip *);
 				sum = in_pseudo(ip->ip_src.s_addr,
-					ip->ip_dst.s_addr, htonl((u_short)len +
-					m->m_pkthdr.csum_data + IPPROTO_UDP));
+				ip->ip_dst.s_addr, htonl((u_short)len +
+				m->m_pkthdr.csum_data + IPPROTO_UDP));
 			}
 			sum ^= 0xffff;
 			++hw_assist;
-                }
+		}
 		break;
 	case IPPROTO_ICMP:
 #ifdef INET6
@@ -6827,6 +6475,7 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t a
 	return (0);
 }
 #else /* !__FreeBSD__ */
+
 /*
  * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
  *   off is the offset where the protocol header starts
@@ -6919,7 +6568,37 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
 	m->m_pkthdr.csum_flags |= flag_ok;
 	return (0);
 }
-#endif /* __FreeBSD__ */
+#endif
+
+#ifndef __FreeBSD__
+struct pf_divert *
+pf_find_divert(struct mbuf *m)
+{
+	struct m_tag    *mtag;
+
+	if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL)
+		return (NULL);
+
+	return ((struct pf_divert *)(mtag + 1));
+}
+
+struct pf_divert *
+pf_get_divert(struct mbuf *m)
+{
+	struct m_tag    *mtag;
+
+	if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL) {
+		mtag = m_tag_get(PACKET_TAG_PF_DIVERT, sizeof(struct pf_divert),
+		    M_NOWAIT);
+		if (mtag == NULL)
+			return (NULL);
+		bzero(mtag + 1, sizeof(struct pf_divert));
+		m_tag_prepend(m, mtag);
+	}
+
+	return ((struct pf_divert *)(mtag + 1));
+}
+#endif
 
 #ifdef INET
 int
@@ -6934,8 +6613,14 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 	struct pfi_kif		*kif;
 	u_short			 action, reason = 0, log = 0;
 	struct mbuf		*m = *m0;
-	struct ip		*h = NULL;	/* make the compiler happy */
+#ifdef __FreeBSD__
+	struct ip		*h = NULL;
+	struct m_tag		*ipfwtag;
+	struct pf_rule		*a = NULL, *r = &V_pf_default_rule, *tr, *nr;
+#else
+	struct ip		*h;
 	struct pf_rule		*a = NULL, *r = &pf_default_rule, *tr, *nr;
+#endif
 	struct pf_state		*s = NULL;
 	struct pf_ruleset	*ruleset = NULL;
 	struct pf_pdesc		 pd;
@@ -6943,44 +6628,32 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 
 #ifdef __FreeBSD__
 	PF_LOCK();
-#endif
-	if (!pf_status.running)
-#ifdef __FreeBSD__
+	if (!V_pf_status.running)
 	{
 		PF_UNLOCK();
-#endif
 		return (PF_PASS);
-#ifdef __FreeBSD__
 	}
+#else
+	if (!pf_status.running)
+		return (PF_PASS);
 #endif
 
 	memset(&pd, 0, sizeof(pd));
-	if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
 #ifdef __FreeBSD__
+	if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
 		PF_UNLOCK();
-#endif
 		DPFPRINTF(PF_DEBUG_URGENT,
 		    ("pf_test: pf_get_mtag returned NULL\n"));
 		return (PF_DROP);
 	}
-#ifdef __FreeBSD__
-	if (m->m_flags & M_SKIP_FIREWALL) {
-		PF_UNLOCK();
-		return (PF_PASS);
-	}
-#else
-	if (pd.pf_mtag->flags & PF_TAG_GENERATED)
-		return (PF_PASS);
 #endif
-
-#ifdef __FreeBSD__
-	/* XXX_IMPORT: later */
-#else
+#ifndef __FreeBSD__
 	if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
-		ifp = ifp->if_carpdev;
+		kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif;
+	else
 #endif
+		kif = (struct pfi_kif *)ifp->if_pf_kif;
 
-	kif = (struct pfi_kif *)ifp->if_pf_kif;
 	if (kif == NULL) {
 #ifdef __FreeBSD__
 		PF_UNLOCK();
@@ -6989,12 +6662,15 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 		    ("pf_test: kif == NULL, if_xname %s\n", ifp->if_xname));
 		return (PF_DROP);
 	}
-	if (kif->pfik_flags & PFI_IFLAG_SKIP) {
+	if (kif->pfik_flags & PFI_IFLAG_SKIP)
 #ifdef __FreeBSD__
+	{
 		PF_UNLOCK();
 #endif
 		return (PF_PASS);
+#ifdef __FreeBSD__
 	}
+#endif
 
 #ifdef __FreeBSD__
 	M_ASSERTPKTHDR(m);
@@ -7003,7 +6679,7 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 	if ((m->m_flags & M_PKTHDR) == 0)
 		panic("non-M_PKTHDR is passed to pf_test");
 #endif /* DIAGNOSTIC */
-#endif /* __FreeBSD__ */
+#endif
 
 	if (m->m_pkthdr.len < (int)sizeof(*h)) {
 		action = PF_DROP;
@@ -7012,12 +6688,36 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 		goto done;
 	}
 
+#ifdef __FreeBSD__
+	if (m->m_flags & M_SKIP_FIREWALL) {
+		PF_UNLOCK();
+		return (PF_PASS);
+	}
+#else
+	if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
+		return (PF_PASS);
+#endif
+	
+#ifdef __FreeBSD__
+	if (ip_divert_ptr != NULL &&
+	    ((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) {
+		struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1);
+		if (rr->info & IPFW_IS_DIVERT && rr->rulenum == 0) {
+			pd.pf_mtag->flags |= PF_PACKET_LOOPED;
+			m_tag_delete(m, ipfwtag);
+		}
+		if (pd.pf_mtag->flags & PF_FASTFWD_OURS_PRESENT) {
+			m->m_flags |= M_FASTFWD_OURS;
+			pd.pf_mtag->flags &= ~PF_FASTFWD_OURS_PRESENT;
+		}
+	} else
+#endif
 	/* We do IP header normalization and packet reassembly here */
 	if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
 		action = PF_DROP;
 		goto done;
 	}
-	m = *m0;
+	m = *m0;	/* pf_normalize messes with m0 */
 	h = mtod(m, struct ip *);
 
 	off = h->ip_hl << 2;
@@ -7030,9 +6730,13 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 
 	pd.src = (struct pf_addr *)&h->ip_src;
 	pd.dst = (struct pf_addr *)&h->ip_dst;
-	PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
+	pd.sport = pd.dport = NULL;
 	pd.ip_sum = &h->ip_sum;
+	pd.proto_sum = NULL;
 	pd.proto = h->ip_p;
+	pd.dir = dir;
+	pd.sidx = (dir == PF_IN) ? 0 : 1;
+	pd.didx = (dir == PF_IN) ? 1 : 0;
 	pd.af = AF_INET;
 	pd.tos = h->ip_tos;
 	pd.tot_len = ntohs(h->ip_len);
@@ -7056,12 +6760,6 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 			log = action != PF_PASS;
 			goto done;
 		}
-		if (dir == PF_IN && pf_check_proto_cksum(m, off,
-		    ntohs(h->ip_len) - off, IPPROTO_TCP, AF_INET)) {
-			REASON_SET(&reason, PFRES_PROTCKSUM);
-			action = PF_DROP;
-			goto done;
-		}
 		pd.p_len = pd.tot_len - off - (th.th_off << 2);
 		if ((th.th_flags & TH_ACK) && pd.p_len == 0)
 			pqid = 1;
@@ -7071,18 +6769,23 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 		action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
 		    &reason);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_tcp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_tcp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, &ipintrq);
 #endif
 		break;
@@ -7097,12 +6800,6 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 			log = action != PF_PASS;
 			goto done;
 		}
-		if (dir == PF_IN && uh.uh_sum && pf_check_proto_cksum(m,
-		    off, ntohs(h->ip_len) - off, IPPROTO_UDP, AF_INET)) {
-			action = PF_DROP;
-			REASON_SET(&reason, PFRES_PROTCKSUM);
-			goto done;
-		}
 		if (uh.uh_dport == 0 ||
 		    ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
 		    ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
@@ -7112,18 +6809,23 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 		}
 		action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_udp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_udp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, &ipintrq);
 #endif
 		break;
@@ -7138,47 +6840,60 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
 			log = action != PF_PASS;
 			goto done;
 		}
-		if (dir == PF_IN && pf_check_proto_cksum(m, off,
-		    ntohs(h->ip_len) - off, IPPROTO_ICMP, AF_INET)) {
-			action = PF_DROP;
-			REASON_SET(&reason, PFRES_PROTCKSUM);
-			goto done;
-		}
 		action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd,
 		    &reason);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_icmp(&r, &s, dir, kif,
-			    m, off, h, &pd, &a, &ruleset, NULL);
+			action = pf_test_rule(&r, &s, dir, kif,
+			    m, off, h, &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_icmp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, &ipintrq);
 #endif
 		break;
 	}
 
+#ifdef INET6
+	case IPPROTO_ICMPV6: {
+		action = PF_DROP;
+		DPFPRINTF(PF_DEBUG_MISC,
+		    ("pf: dropping IPv4 packet with ICMPv6 payload\n"));
+		goto done;
+	}
+#endif
+
 	default:
-		action = pf_test_state_other(&s, dir, kif, &pd);
+		action = pf_test_state_other(&s, dir, kif, m, &pd);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_other(&r, &s, dir, kif, m, off, h,
-			    &pd, &a, &ruleset, NULL);
+			action = pf_test_rule(&r, &s, dir, kif, m, off, h,
+			    &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_other(&r, &s, dir, kif, m, off, h,
+			action = pf_test_rule(&r, &s, dir, kif, m, off, h,
 			    &pd, &a, &ruleset, &ipintrq);
 #endif
 		break;
@@ -7195,17 +6910,37 @@ done:
 	}
 
 	if ((s && s->tag) || r->rtableid)
-		pf_tag_packet(m, pd.pf_mtag, s ? s->tag : 0, r->rtableid);
+#ifdef __FreeBSD__
+		pf_tag_packet(m, s ? s->tag : 0, r->rtableid, pd.pf_mtag);
+#else
+		pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
+#endif
+
+	if (dir == PF_IN && s && s->key[PF_SK_STACK])
+#ifdef __FreeBSD__
+		pd.pf_mtag->statekey = s->key[PF_SK_STACK];
+#else
+		m->m_pkthdr.pf.statekey = s->key[PF_SK_STACK];
+#endif
 
 #ifdef ALTQ
 	if (action == PF_PASS && r->qid) {
+#ifdef __FreeBSD__
 		if (pqid || (pd.tos & IPTOS_LOWDELAY))
 			pd.pf_mtag->qid = r->pqid;
 		else
 			pd.pf_mtag->qid = r->qid;
 		/* add hints for ecn */
-		pd.pf_mtag->af = AF_INET;
 		pd.pf_mtag->hdr = h;
+
+#else
+		if (pqid || (pd.tos & IPTOS_LOWDELAY))
+			m->m_pkthdr.pf.qid = r->pqid;
+		else
+			m->m_pkthdr.pf.qid = r->qid;
+		/* add hints for ecn */
+		m->m_pkthdr.pf.hdr = h;
+#endif
 	}
 #endif /* ALTQ */
 
@@ -7219,7 +6954,55 @@ done:
 	    (s->nat_rule.ptr->action == PF_RDR ||
 	    s->nat_rule.ptr->action == PF_BINAT) &&
 	    (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
-		pd.pf_mtag->flags |= PF_TAG_TRANSLATE_LOCALHOST;
+#ifdef __FreeBSD__
+		m->m_flags |= M_SKIP_FIREWALL;
+#else
+		m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
+#endif
+
+#ifdef __FreeBSD__
+	if (action == PF_PASS && r->divert.port &&
+	    ip_divert_ptr != NULL && !PACKET_LOOPED()) {
+
+		ipfwtag = m_tag_alloc(MTAG_IPFW_RULE, 0,
+				sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO);
+		if (ipfwtag != NULL) {
+			((struct ipfw_rule_ref *)(ipfwtag+1))->info = r->divert.port;
+			((struct ipfw_rule_ref *)(ipfwtag+1))->rulenum = dir;
+
+			m_tag_prepend(m, ipfwtag);
+
+			PF_UNLOCK();
+
+			if (m->m_flags & M_FASTFWD_OURS) {
+				pd.pf_mtag->flags |= PF_FASTFWD_OURS_PRESENT;
+				m->m_flags &= ~M_FASTFWD_OURS;
+			}
+
+			ip_divert_ptr(*m0,
+				dir ==  PF_IN ? DIR_IN : DIR_OUT);
+			*m0 = NULL;
+			return (action);
+		} else {
+			/* XXX: ipfw has the same behaviour! */
+			action = PF_DROP;
+			REASON_SET(&reason, PFRES_MEMORY);
+			log = 1;
+			DPFPRINTF(PF_DEBUG_MISC,
+			    ("pf: failed to allocate divert tag\n"));
+		}
+	}
+#else
+	if (dir == PF_IN && action == PF_PASS && r->divert.port) {
+		struct pf_divert *divert;
+
+		if ((divert = pf_get_divert(m))) {
+			m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED;
+			divert->port = r->divert.port;
+			divert->addr.ipv4 = r->divert.addr.v4;
+		}
+	}
+#endif
 
 	if (log) {
 		struct pf_rule *lr;
@@ -7263,53 +7046,44 @@ done:
 		}
 		tr = r;
 		nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
-		if (nr != NULL) {
-			struct pf_addr *x;
-			/*
-			 * XXX: we need to make sure that the addresses
-			 * passed to pfr_update_stats() are the same than
-			 * the addresses used during matching (pfr_match)
-			 */
-			if (r == &pf_default_rule) {
-				tr = nr;
-				x = (s == NULL || s->direction == dir) ?
-				    &pd.baddr : &pd.naddr;
-			} else
-				x = (s == NULL || s->direction == dir) ?
-				    &pd.naddr : &pd.baddr;
-			if (x == &pd.baddr || s == NULL) {
-				/* we need to change the address */
-				if (dir == PF_OUT)
-					pd.src = x;
-				else
-					pd.dst = x;
-			}
-		}
+#ifdef __FreeBSD__
+		if (nr != NULL && r == &V_pf_default_rule)
+#else
+		if (nr != NULL && r == &pf_default_rule)
+#endif
+			tr = nr;
 		if (tr->src.addr.type == PF_ADDR_TABLE)
-			pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
-			    s->direction == dir) ? pd.src : pd.dst, pd.af,
-			    pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
-			    tr->src.neg);
+			pfr_update_stats(tr->src.addr.p.tbl,
+			    (s == NULL) ? pd.src :
+			    &s->key[(s->direction == PF_IN)]->
+				addr[(s->direction == PF_OUT)],
+			    pd.af, pd.tot_len, dir == PF_OUT,
+			    r->action == PF_PASS, tr->src.neg);
 		if (tr->dst.addr.type == PF_ADDR_TABLE)
-			pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
-			    s->direction == dir) ? pd.dst : pd.src, pd.af,
-			    pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
-			    tr->dst.neg);
+			pfr_update_stats(tr->dst.addr.p.tbl,
+			    (s == NULL) ? pd.dst :
+			    &s->key[(s->direction == PF_IN)]->
+				addr[(s->direction == PF_IN)],
+			    pd.af, pd.tot_len, dir == PF_OUT,
+			    r->action == PF_PASS, tr->dst.neg);
 	}
 
-
-	if (action == PF_SYNPROXY_DROP) {
+	switch (action) {
+	case PF_SYNPROXY_DROP:
 		m_freem(*m0);
+	case PF_DEFER:
 		*m0 = NULL;
 		action = PF_PASS;
-	} else if (r->rt)
+		break;
+	default:
 		/* pf_route can free the mbuf causing *m0 to become NULL */
-		pf_route(m0, r, dir, ifp, s, &pd);
-
+		if (r->rt)
+			pf_route(m0, r, dir, kif->pfik_ifp, s, &pd);
+		break;
+	}
 #ifdef __FreeBSD__
 	PF_UNLOCK();
 #endif
-
 	return (action);
 }
 #endif /* INET */
@@ -7327,8 +7101,13 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 	struct pfi_kif		*kif;
 	u_short			 action, reason = 0, log = 0;
 	struct mbuf		*m = *m0, *n = NULL;
+#ifdef __FreeBSD__
+	struct ip6_hdr		*h = NULL;
+	struct pf_rule		*a = NULL, *r = &V_pf_default_rule, *tr, *nr;
+#else
 	struct ip6_hdr		*h;
 	struct pf_rule		*a = NULL, *r = &pf_default_rule, *tr, *nr;
+#endif
 	struct pf_state		*s = NULL;
 	struct pf_ruleset	*ruleset = NULL;
 	struct pf_pdesc		 pd;
@@ -7336,38 +7115,31 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 
 #ifdef __FreeBSD__
 	PF_LOCK();
-#endif
-
-	if (!pf_status.running)
-#ifdef __FreeBSD__
-	{
+	if (!V_pf_status.running) {
 		PF_UNLOCK();
-#endif
 		return (PF_PASS);
-#ifdef __FreeBSD__
 	}
+#else
+	if (!pf_status.running)
+		return (PF_PASS);
 #endif
 
 	memset(&pd, 0, sizeof(pd));
-	if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
 #ifdef __FreeBSD__
+	if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
 		PF_UNLOCK();
-#endif
 		DPFPRINTF(PF_DEBUG_URGENT,
-		    ("pf_test6: pf_get_mtag returned NULL\n"));
+		    ("pf_test: pf_get_mtag returned NULL\n"));
 		return (PF_DROP);
 	}
-	if (pd.pf_mtag->flags & PF_TAG_GENERATED)
-		return (PF_PASS);
-
-#ifdef __FreeBSD__
-	/* XXX_IMPORT: later */
-#else
+#endif
+#ifndef __FreeBSD__
 	if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
-		ifp = ifp->if_carpdev;
+		kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif;
+	else
 #endif
+		kif = (struct pfi_kif *)ifp->if_pf_kif;
 
-	kif = (struct pfi_kif *)ifp->if_pf_kif;
 	if (kif == NULL) {
 #ifdef __FreeBSD__
 		PF_UNLOCK();
@@ -7376,12 +7148,15 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 		    ("pf_test6: kif == NULL, if_xname %s\n", ifp->if_xname));
 		return (PF_DROP);
 	}
-	if (kif->pfik_flags & PFI_IFLAG_SKIP) {
+	if (kif->pfik_flags & PFI_IFLAG_SKIP)
 #ifdef __FreeBSD__
+	{
 		PF_UNLOCK();
 #endif
 		return (PF_PASS);
+#ifdef __FreeBSD__
 	}
+#endif
 
 #ifdef __FreeBSD__
 	M_ASSERTPKTHDR(m);
@@ -7392,10 +7167,6 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 #endif /* DIAGNOSTIC */
 #endif
 
-#ifdef __FreeBSD__
-	h = NULL;	/* make the compiler happy */
-#endif
-
 	if (m->m_pkthdr.len < (int)sizeof(*h)) {
 		action = PF_DROP;
 		REASON_SET(&reason, PFRES_SHORT);
@@ -7403,12 +7174,19 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 		goto done;
 	}
 
+#ifdef __FreeBSD__
+	if (pd.pf_mtag->flags & PF_TAG_GENERATED)
+#else
+	if (m->m_pkthdr.pf.flags & PF_TAG_GENERATED)
+#endif
+		return (PF_PASS);
+
 	/* We do IP header normalization and packet reassembly here */
 	if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
 		action = PF_DROP;
 		goto done;
 	}
-	m = *m0;
+	m = *m0;	/* pf_normalize messes with m0 */
 	h = mtod(m, struct ip6_hdr *);
 
 #if 1
@@ -7425,8 +7203,12 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 
 	pd.src = (struct pf_addr *)&h->ip6_src;
 	pd.dst = (struct pf_addr *)&h->ip6_dst;
-	PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
+	pd.sport = pd.dport = NULL;
 	pd.ip_sum = NULL;
+	pd.proto_sum = NULL;
+	pd.dir = dir;
+	pd.sidx = (dir == PF_IN) ? 0 : 1;
+	pd.didx = (dir == PF_IN) ? 1 : 0;
 	pd.af = AF_INET6;
 	pd.tos = 0;
 	pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
@@ -7470,7 +7252,7 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 				log = 1;
 				goto done;
 			}
-			/* fallthrough */
+			/* FALLTHROUGH */
 		}
 		case IPPROTO_AH:
 		case IPPROTO_HOPOPTS:
@@ -7515,13 +7297,6 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 			log = action != PF_PASS;
 			goto done;
 		}
-		if (dir == PF_IN && pf_check_proto_cksum(n, off,
-		    ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
-		    IPPROTO_TCP, AF_INET6)) {
-			action = PF_DROP;
-			REASON_SET(&reason, PFRES_PROTCKSUM);
-			goto done;
-		}
 		pd.p_len = pd.tot_len - off - (th.th_off << 2);
 		action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
 		if (action == PF_DROP)
@@ -7529,18 +7304,23 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 		action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
 		    &reason);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_tcp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_tcp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, &ip6intrq);
 #endif
 		break;
@@ -7555,13 +7335,6 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 			log = action != PF_PASS;
 			goto done;
 		}
-		if (dir == PF_IN && uh.uh_sum && pf_check_proto_cksum(n,
-		    off, ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
-		    IPPROTO_UDP, AF_INET6)) {
-			action = PF_DROP;
-			REASON_SET(&reason, PFRES_PROTCKSUM);
-			goto done;
-		}
 		if (uh.uh_dport == 0 ||
 		    ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
 		    ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
@@ -7571,23 +7344,35 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 		}
 		action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_udp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_udp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, &ip6intrq);
 #endif
 		break;
 	}
 
+	case IPPROTO_ICMP: {
+		action = PF_DROP;
+		DPFPRINTF(PF_DEBUG_MISC,
+		    ("pf: dropping IPv6 packet with ICMPv4 payload\n"));
+		goto done;
+	}
+
 	case IPPROTO_ICMPV6: {
 		struct icmp6_hdr	ih;
 
@@ -7597,54 +7382,62 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
 			log = action != PF_PASS;
 			goto done;
 		}
-		if (dir == PF_IN && pf_check_proto_cksum(n, off,
-		    ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
-		    IPPROTO_ICMPV6, AF_INET6)) {
-			action = PF_DROP;
-			REASON_SET(&reason, PFRES_PROTCKSUM);
-			goto done;
-		}
 		action = pf_test_state_icmp(&s, dir, kif,
 		    m, off, h, &pd, &reason);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_icmp(&r, &s, dir, kif,
-			    m, off, h, &pd, &a, &ruleset, NULL);
+			action = pf_test_rule(&r, &s, dir, kif,
+			    m, off, h, &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_icmp(&r, &s, dir, kif,
+			action = pf_test_rule(&r, &s, dir, kif,
 			    m, off, h, &pd, &a, &ruleset, &ip6intrq);
 #endif
 		break;
 	}
 
 	default:
-		action = pf_test_state_other(&s, dir, kif, &pd);
+		action = pf_test_state_other(&s, dir, kif, m, &pd);
 		if (action == PF_PASS) {
-#if NPFSYNC
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+			if (pfsync_update_state_ptr != NULL)
+				pfsync_update_state_ptr(s);
+#else
 			pfsync_update_state(s);
+#endif
 #endif /* NPFSYNC */
 			r = s->rule.ptr;
 			a = s->anchor.ptr;
 			log = s->log;
 		} else if (s == NULL)
 #ifdef __FreeBSD__
-			action = pf_test_other(&r, &s, dir, kif, m, off, h,
-			    &pd, &a, &ruleset, NULL);
+			action = pf_test_rule(&r, &s, dir, kif, m, off, h,
+			    &pd, &a, &ruleset, NULL, inp);
 #else
-			action = pf_test_other(&r, &s, dir, kif, m, off, h,
+			action = pf_test_rule(&r, &s, dir, kif, m, off, h,
 			    &pd, &a, &ruleset, &ip6intrq);
 #endif
 		break;
 	}
 
 done:
+	if (n != m) {
+		m_freem(n);
+		n = NULL;
+	}
+
 	/* handle dangerous IPv6 extension headers. */
 	if (action == PF_PASS && rh_cnt &&
 	    !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
@@ -7656,17 +7449,36 @@ done:
 	}
 
 	if ((s && s->tag) || r->rtableid)
-		pf_tag_packet(m, pd.pf_mtag, s ? s->tag : 0, r->rtableid);
+#ifdef __FreeBSD__
+		pf_tag_packet(m, s ? s->tag : 0, r->rtableid, pd.pf_mtag);
+#else
+		pf_tag_packet(m, s ? s->tag : 0, r->rtableid);
+#endif
+
+	if (dir == PF_IN && s && s->key[PF_SK_STACK])
+#ifdef __FreeBSD__
+		pd.pf_mtag->statekey = s->key[PF_SK_STACK];
+#else
+		m->m_pkthdr.pf.statekey = s->key[PF_SK_STACK];
+#endif
 
 #ifdef ALTQ
 	if (action == PF_PASS && r->qid) {
+#ifdef __FreeBSD__
 		if (pd.tos & IPTOS_LOWDELAY)
 			pd.pf_mtag->qid = r->pqid;
 		else
 			pd.pf_mtag->qid = r->qid;
 		/* add hints for ecn */
-		pd.pf_mtag->af = AF_INET6;
 		pd.pf_mtag->hdr = h;
+#else
+		if (pd.tos & IPTOS_LOWDELAY)
+			m->m_pkthdr.pf.qid = r->pqid;
+		else
+			m->m_pkthdr.pf.qid = r->qid;
+		/* add hints for ecn */
+		m->m_pkthdr.pf.hdr = h;
+#endif
 	}
 #endif /* ALTQ */
 
@@ -7675,7 +7487,27 @@ done:
 	    (s->nat_rule.ptr->action == PF_RDR ||
 	    s->nat_rule.ptr->action == PF_BINAT) &&
 	    IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))
-		pd.pf_mtag->flags |= PF_TAG_TRANSLATE_LOCALHOST;
+#ifdef __FreeBSD__
+		m->m_flags |= M_SKIP_FIREWALL;
+#else
+		m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
+#endif
+
+#ifdef __FreeBSD__
+	/* XXX: Anybody working on it?! */
+	if (r->divert.port)
+		printf("pf: divert(9) is not supported for IPv6\n");
+#else
+	if (dir == PF_IN && action == PF_PASS && r->divert.port) {
+		struct pf_divert *divert;
+
+		if ((divert = pf_get_divert(m))) {
+			m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED;
+			divert->port = r->divert.port;
+			divert->addr.ipv6 = r->divert.addr.v6;
+		}
+	}
+#endif
 
 	if (log) {
 		struct pf_rule *lr;
@@ -7719,48 +7551,39 @@ done:
 		}
 		tr = r;
 		nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
-		if (nr != NULL) {
-			struct pf_addr *x;
-			/*
-			 * XXX: we need to make sure that the addresses
-			 * passed to pfr_update_stats() are the same than
-			 * the addresses used during matching (pfr_match)
-			 */
-			if (r == &pf_default_rule) {
-				tr = nr;
-				x = (s == NULL || s->direction == dir) ?
-				    &pd.baddr : &pd.naddr;
-			} else {
-				x = (s == NULL || s->direction == dir) ?
-				    &pd.naddr : &pd.baddr;
-			}
-			if (x == &pd.baddr || s == NULL) {
-				if (dir == PF_OUT)
-					pd.src = x;
-				else
-					pd.dst = x;
-			}
-		}
+#ifdef __FreeBSD__
+		if (nr != NULL && r == &V_pf_default_rule)
+#else
+		if (nr != NULL && r == &pf_default_rule)
+#endif
+			tr = nr;
 		if (tr->src.addr.type == PF_ADDR_TABLE)
-			pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
-			    s->direction == dir) ? pd.src : pd.dst, pd.af,
-			    pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
-			    tr->src.neg);
+			pfr_update_stats(tr->src.addr.p.tbl,
+			    (s == NULL) ? pd.src :
+			    &s->key[(s->direction == PF_IN)]->addr[0],
+			    pd.af, pd.tot_len, dir == PF_OUT,
+			    r->action == PF_PASS, tr->src.neg);
 		if (tr->dst.addr.type == PF_ADDR_TABLE)
-			pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
-			    s->direction == dir) ? pd.dst : pd.src, pd.af,
-			    pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
-			    tr->dst.neg);
+			pfr_update_stats(tr->dst.addr.p.tbl,
+			    (s == NULL) ? pd.dst :
+			    &s->key[(s->direction == PF_IN)]->addr[1],
+			    pd.af, pd.tot_len, dir == PF_OUT,
+			    r->action == PF_PASS, tr->dst.neg);
 	}
 
-
-	if (action == PF_SYNPROXY_DROP) {
+	switch (action) {
+	case PF_SYNPROXY_DROP:
 		m_freem(*m0);
+	case PF_DEFER:
 		*m0 = NULL;
 		action = PF_PASS;
-	} else if (r->rt)
+		break;
+	default:
 		/* pf_route6 can free the mbuf causing *m0 to become NULL */
-		pf_route6(m0, r, dir, ifp, s, &pd);
+		if (r->rt)
+			pf_route6(m0, r, dir, kif->pfik_ifp, s, &pd);
+		break;
+	}
 
 #ifdef __FreeBSD__
 	PF_UNLOCK();
@@ -7782,3 +7605,20 @@ pf_check_congestion(struct ifqueue *ifq)
 		return (0);
 #endif
 }
+
+/*
+ * must be called whenever any addressing information such as
+ * address, port, protocol has changed
+ */
+void
+pf_pkt_addr_changed(struct mbuf *m)
+{
+#ifdef __FreeBSD__
+	struct pf_mtag	*pf_tag;
+
+	if ((pf_tag = pf_find_mtag(m)) != NULL)
+		pf_tag->statekey = NULL;
+#else
+	m->m_pkthdr.pf.statekey = NULL;
+#endif
+}
diff --git a/sys/contrib/pf/net/pf_if.c b/sys/contrib/pf/net/pf_if.c
index 156fb22..6336c79 100644
--- a/sys/contrib/pf/net/pf_if.c
+++ b/sys/contrib/pf/net/pf_if.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf_if.c,v 1.46 2006/12/13 09:01:59 itojun Exp $ */
+/*	$OpenBSD: pf_if.c,v 1.54 2008/06/14 16:55:28 mk Exp $ */
 
 /*
  * Copyright 2005 Henning Brauer 
@@ -54,6 +54,9 @@ __FBSDID("$FreeBSD$");
 #include 
 #endif
 #include 
+#ifndef __FreeBSD__
+#include 
+#endif
 
 #include 
 #include 
@@ -73,25 +76,35 @@ __FBSDID("$FreeBSD$");
 #include 
 #endif /* INET6 */
 
-struct pfi_kif		 *pfi_all = NULL;
-struct pfi_statehead	  pfi_statehead;
 #ifdef __FreeBSD__
-uma_zone_t		  pfi_addr_pl;
+VNET_DEFINE(struct pfi_kif *,	 pfi_all);
+VNET_DEFINE(uma_zone_t,		 pfi_addr_pl);
+VNET_DEFINE(struct pfi_ifhead,	 pfi_ifs);
+#define	V_pfi_ifs		 VNET(pfi_ifs)
+VNET_DEFINE(long,		 pfi_update);
+#define	V_pfi_update		 VNET(pfi_update)
+VNET_DEFINE(struct pfr_addr *,	 pfi_buffer);
+#define	V_pfi_buffer		 VNET(pfi_buffer)
+VNET_DEFINE(int,		 pfi_buffer_cnt);
+#define	V_pfi_buffer_cnt	 VNET(pfi_buffer_cnt)
+VNET_DEFINE(int,		 pfi_buffer_max);
+#define	V_pfi_buffer_max	 VNET(pfi_buffer_max)
 #else
+struct pfi_kif		 *pfi_all = NULL;
 struct pool		  pfi_addr_pl;
-#endif
 struct pfi_ifhead	  pfi_ifs;
 long			  pfi_update = 1;
 struct pfr_addr		 *pfi_buffer;
 int			  pfi_buffer_cnt;
 int			  pfi_buffer_max;
+#endif
 #ifdef __FreeBSD__
-eventhandler_tag	  pfi_attach_cookie = NULL;
-eventhandler_tag	  pfi_detach_cookie = NULL;
-eventhandler_tag	  pfi_attach_group_cookie = NULL;
-eventhandler_tag	  pfi_change_group_cookie = NULL;
-eventhandler_tag	  pfi_detach_group_cookie = NULL;
-eventhandler_tag	  pfi_ifaddr_event_cookie = NULL;
+eventhandler_tag	 pfi_attach_cookie;
+eventhandler_tag	 pfi_detach_cookie;
+eventhandler_tag	 pfi_attach_group_cookie;
+eventhandler_tag	 pfi_change_group_cookie;
+eventhandler_tag	 pfi_detach_group_cookie;
+eventhandler_tag	 pfi_ifaddr_event_cookie;
 #endif
 
 void		 pfi_kif_update(struct pfi_kif *);
@@ -107,11 +120,10 @@ int		 pfi_unmask(void *);
 #ifdef __FreeBSD__
 void		 pfi_attach_ifnet_event(void * __unused, struct ifnet *);
 void		 pfi_detach_ifnet_event(void * __unused, struct ifnet *);
-void		 pfi_attach_group_event(void * __unused, struct ifg_group *);
-void		 pfi_change_group_event(void * __unused, char *);
-void		 pfi_detach_group_event(void * __unused, struct ifg_group *);
+void		 pfi_attach_group_event(void *, struct ifg_group *);
+void		 pfi_change_group_event(void *, char *);
+void		 pfi_detach_group_event(void *, struct ifg_group *);
 void		 pfi_ifaddr_event(void * __unused, struct ifnet *);
-
 #endif
 
 RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
@@ -123,22 +135,31 @@ RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
 void
 pfi_initialize(void)
 {
-
+#ifdef __FreeBSD__
+	if (V_pfi_all != NULL)	/* already initialized */
+#else
 	if (pfi_all != NULL)	/* already initialized */
+#endif
 		return;
 
-	TAILQ_INIT(&pfi_statehead);
 #ifndef __FreeBSD__
-	pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
+	pool_init(&V_pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
 	    "pfiaddrpl", &pool_allocator_nointr);
 #endif
+#ifdef __FreeBSD__
+	V_pfi_buffer_max = 64;
+	V_pfi_buffer = malloc(V_pfi_buffer_max * sizeof(*V_pfi_buffer),
+	    PFI_MTYPE, M_WAITOK);
+
+	if ((V_pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
+#else
 	pfi_buffer_max = 64;
 	pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer),
 	    PFI_MTYPE, M_WAITOK);
 
 	if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
+#endif
 		panic("pfi_kif_get for pfi_all failed");
-
 #ifdef __FreeBSD__
 	struct ifg_group *ifg;
 	struct ifnet *ifp;
@@ -155,11 +176,11 @@ pfi_initialize(void)
 	pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
 	    pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
 	pfi_attach_group_cookie = EVENTHANDLER_REGISTER(group_attach_event,
-	    pfi_attach_group_event, NULL, EVENTHANDLER_PRI_ANY);
+	    pfi_attach_group_event, curvnet, EVENTHANDLER_PRI_ANY);
 	pfi_change_group_cookie = EVENTHANDLER_REGISTER(group_change_event,
-	    pfi_change_group_event, NULL, EVENTHANDLER_PRI_ANY);
+	    pfi_change_group_event, curvnet, EVENTHANDLER_PRI_ANY);
 	pfi_detach_group_cookie = EVENTHANDLER_REGISTER(group_detach_event,
-	    pfi_detach_group_event, NULL, EVENTHANDLER_PRI_ANY);
+	    pfi_detach_group_event, curvnet, EVENTHANDLER_PRI_ANY);
 	pfi_ifaddr_event_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
 	    pfi_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY);
 #endif
@@ -180,18 +201,18 @@ pfi_cleanup(void)
 	EVENTHANDLER_DEREGISTER(ifaddr_event, pfi_ifaddr_event_cookie);
 	PF_LOCK();
 
-	pfi_all = NULL;
-	while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) {
+	V_pfi_all = NULL;
+	while ((p = RB_MIN(pfi_ifhead, &V_pfi_ifs))) {
 		if (p->pfik_rules || p->pfik_states) {
 			printf("pfi_cleanup: dangling refs for %s\n",
 			    p->pfik_name);
 		}
 
-		RB_REMOVE(pfi_ifhead, &pfi_ifs, p);
+		RB_REMOVE(pfi_ifhead, &V_pfi_ifs, p);
 		free(p, PFI_MTYPE);
 	}
 
-	free(pfi_buffer, PFI_MTYPE);
+	free(V_pfi_buffer, PFI_MTYPE);
 }
 #endif
 
@@ -203,18 +224,21 @@ pfi_kif_get(const char *kif_name)
 
 	bzero(&s, sizeof(s));
 	strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
+#ifdef __FreeBSD__
+	if ((kif = RB_FIND(pfi_ifhead, &V_pfi_ifs, (struct pfi_kif *)&s)) != NULL)
+#else
 	if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL)
+#endif
 		return (kif);
 
 	/* create new one */
 #ifdef __FreeBSD__
-	if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT)) == NULL)
+	if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT | M_ZERO)) == NULL)
 #else
-	if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT)) == NULL)
+	if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT|M_ZERO)) == NULL)
 #endif
 		return (NULL);
 
-	bzero(kif, sizeof(*kif));
 	strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
 #ifdef __FreeBSD__
 	/*
@@ -230,7 +254,12 @@ pfi_kif_get(const char *kif_name)
 #endif
 	TAILQ_INIT(&kif->pfik_dynaddrs);
 
+#ifdef __FreeBSD__
+	RB_INSERT(pfi_ifhead, &V_pfi_ifs, kif);
+#else
 	RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
+#endif
+
 	return (kif);
 }
 
@@ -242,8 +271,7 @@ pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
 		kif->pfik_rules++;
 		break;
 	case PFI_KIF_REF_STATE:
-		if (!kif->pfik_states++)
-			TAILQ_INSERT_TAIL(&pfi_statehead, kif, pfik_w_states);
+		kif->pfik_states++;
 		break;
 	default:
 		panic("pfi_kif_ref with unknown type");
@@ -271,20 +299,27 @@ pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
 			printf("pfi_kif_unref: state refcount <= 0\n");
 			return;
 		}
-		if (!--kif->pfik_states)
-			TAILQ_REMOVE(&pfi_statehead, kif, pfik_w_states);
+		kif->pfik_states--;
 		break;
 	default:
 		panic("pfi_kif_unref with unknown type");
 	}
 
+#ifdef __FreeBSD__
+	if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == V_pfi_all)
+#else
 	if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
+#endif
 		return;
 
 	if (kif->pfik_rules || kif->pfik_states)
 		return;
 
+#ifdef __FreeBSD__
+	RB_REMOVE(pfi_ifhead, &V_pfi_ifs, kif);
+#else
 	RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
+#endif
 	free(kif, PFI_MTYPE);
 }
 
@@ -312,7 +347,11 @@ pfi_attach_ifnet(struct ifnet *ifp)
 
 	pfi_initialize();
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	V_pfi_update++;
+#else
 	pfi_update++;
+#endif
 	if ((kif = pfi_kif_get(ifp->if_xname)) == NULL)
 		panic("pfi_kif_get failed");
 
@@ -341,7 +380,11 @@ pfi_detach_ifnet(struct ifnet *ifp)
 		return;
 
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	V_pfi_update++;
+#else
 	pfi_update++;
+#endif
 #ifndef __FreeBSD__
 	hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie);
 #endif
@@ -361,7 +404,11 @@ pfi_attach_ifgroup(struct ifg_group *ifg)
 
 	pfi_initialize();
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	V_pfi_update++;
+#else
 	pfi_update++;
+#endif
 	if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL)
 		panic("pfi_kif_get failed");
 
@@ -381,7 +428,11 @@ pfi_detach_ifgroup(struct ifg_group *ifg)
 		return;
 
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	V_pfi_update++;
+#else
 	pfi_update++;
+#endif
 
 	kif->pfik_group = NULL;
 	ifg->ifg_pf_kif = NULL;
@@ -396,7 +447,11 @@ pfi_group_change(const char *group)
 	int			 s;
 
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	V_pfi_update++;
+#else
 	pfi_update++;
+#endif
 	if ((kif = pfi_kif_get(group)) == NULL)
 		panic("pfi_kif_get failed");
 
@@ -450,9 +505,14 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
 
 	if (aw->type != PF_ADDR_DYNIFTL)
 		return (0);
-	if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL)
+#ifdef __FreeBSD__
+	/* XXX: revisit! */
+	if ((dyn = pool_get(&V_pfi_addr_pl, PR_WAITOK | PR_ZERO))
+#else
+	if ((dyn = pool_get(&pfi_addr_pl, PR_WAITOK | PR_LIMITFAIL | PR_ZERO))
+#endif
+	    == NULL)
 		return (1);
-	bzero(dyn, sizeof(*dyn));
 
 	s = splsoftnet();
 	if (!strcmp(aw->v.ifname, "self"))
@@ -485,7 +545,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
 		goto _bad;
 	}
 
-	if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) {
+	if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, 1)) == NULL) {
 		rv = 1;
 		goto _bad;
 	}
@@ -507,7 +567,11 @@ _bad:
 		pf_remove_if_empty_ruleset(ruleset);
 	if (dyn->pfid_kif != NULL)
 		pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
+#ifdef __FreeBSD__
+	pool_put(&V_pfi_addr_pl, dyn);
+#else
 	pool_put(&pfi_addr_pl, dyn);
+#endif
 	splx(s);
 	return (rv);
 }
@@ -541,10 +605,18 @@ pfi_dynaddr_update(struct pfi_dynaddr *dyn)
 	kif = dyn->pfid_kif;
 	kt = dyn->pfid_kt;
 
+#ifdef __FreeBSD__
+	if (kt->pfrkt_larg != V_pfi_update) {
+#else
 	if (kt->pfrkt_larg != pfi_update) {
+#endif
 		/* this table needs to be brought up-to-date */
 		pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
+#ifdef __FreeBSD__
+		kt->pfrkt_larg = V_pfi_update;
+#else
 		kt->pfrkt_larg = pfi_update;
+#endif
 	}
 	pfr_dynaddr_update(kt, dyn);
 }
@@ -555,7 +627,11 @@ pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
 	int			 e, size2 = 0;
 	struct ifg_member	*ifgm;
 
+#ifdef __FreeBSD__
+	V_pfi_buffer_cnt = 0;
+#else
 	pfi_buffer_cnt = 0;
+#endif
 
 	if (kif->pfik_ifp != NULL)
 		pfi_instance_add(kif->pfik_ifp, net, flags);
@@ -563,10 +639,17 @@ pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
 		TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next)
 			pfi_instance_add(ifgm->ifgm_ifp, net, flags);
 
+#ifdef __FreeBSD__
+	if ((e = pfr_set_addrs(&kt->pfrkt_t, V_pfi_buffer, V_pfi_buffer_cnt, &size2,
+	    NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
+		printf("pfi_table_update: cannot set %d new addresses "
+		    "into table %s: %d\n", V_pfi_buffer_cnt, kt->pfrkt_name, e);
+#else
 	if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2,
 	    NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
 		printf("pfi_table_update: cannot set %d new addresses "
 		    "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
+#endif
 }
 
 void
@@ -587,9 +670,9 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags)
 #ifdef __FreeBSD__
 		/*
 		 * XXX: For point-to-point interfaces, (ifname:0) and IPv4,
-		 *	jump over addresses without a proper route to work
-		 *	around a problem with ppp not fully removing the
-		 *	address used during IPCP.
+		 *      jump over addresses without a proper route to work
+		 *      around a problem with ppp not fully removing the
+		 *      address used during IPCP.
 		 */
 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
 		    !(ia->ifa_flags & IFA_ROUTE) &&
@@ -644,15 +727,24 @@ pfi_address_add(struct sockaddr *sa, int af, int net)
 	struct pfr_addr	*p;
 	int		 i;
 
+#ifdef __FreeBSD__
+	if (V_pfi_buffer_cnt >= V_pfi_buffer_max) {
+		int		 new_max = V_pfi_buffer_max * 2;
+#else
 	if (pfi_buffer_cnt >= pfi_buffer_max) {
 		int		 new_max = pfi_buffer_max * 2;
+#endif
 
 		if (new_max > PFI_BUFFER_MAX) {
 			printf("pfi_address_add: address buffer full (%d/%d)\n",
+#ifdef __FreeBSD__
+			    V_pfi_buffer_cnt, PFI_BUFFER_MAX);
+#else
 			    pfi_buffer_cnt, PFI_BUFFER_MAX);
+#endif
 			return;
 		}
-		p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
+		p = malloc(new_max * sizeof(*V_pfi_buffer), PFI_MTYPE,
 #ifdef __FreeBSD__
 		    M_NOWAIT);
 #else
@@ -660,18 +752,34 @@ pfi_address_add(struct sockaddr *sa, int af, int net)
 #endif
 		if (p == NULL) {
 			printf("pfi_address_add: no memory to grow buffer "
+#ifdef __FreeBSD__
+			    "(%d/%d)\n", V_pfi_buffer_cnt, PFI_BUFFER_MAX);
+#else
 			    "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
+#endif
 			return;
 		}
-		memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer));
+#ifdef __FreeBSD__
+		memcpy(V_pfi_buffer, p, V_pfi_buffer_cnt * sizeof(*V_pfi_buffer));
+		/* no need to zero buffer */
+		free(V_pfi_buffer, PFI_MTYPE);
+		V_pfi_buffer = p;
+		V_pfi_buffer_max = new_max;
+#else
+		memcpy(pfi_buffer, p, pfi_buffer_cnt * sizeof(*pfi_buffer));
 		/* no need to zero buffer */
 		free(pfi_buffer, PFI_MTYPE);
 		pfi_buffer = p;
 		pfi_buffer_max = new_max;
+#endif
 	}
 	if (af == AF_INET && net > 32)
 		net = 128;
+#ifdef __FreeBSD__
+	p = V_pfi_buffer + V_pfi_buffer_cnt++;
+#else
 	p = pfi_buffer + pfi_buffer_cnt++;
+#endif
 	bzero(p, sizeof(*p));
 	p->pfra_af = af;
 	p->pfra_net = net;
@@ -704,7 +812,11 @@ pfi_dynaddr_remove(struct pf_addr_wrap *aw)
 	aw->p.dyn->pfid_kif = NULL;
 	pfr_detach_table(aw->p.dyn->pfid_kt);
 	aw->p.dyn->pfid_kt = NULL;
+#ifdef __FreeBSD__
+	pool_put(&V_pfi_addr_pl, aw->p.dyn);
+#else
 	pool_put(&pfi_addr_pl, aw->p.dyn);
+#endif
 	aw->p.dyn = NULL;
 	splx(s);
 }
@@ -725,7 +837,11 @@ pfi_kifaddr_update(void *v)
 	struct pfi_kif		*kif = (struct pfi_kif *)v;
 
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	V_pfi_update++;
+#else
 	pfi_update++;
+#endif
 	pfi_kif_update(kif);
 	splx(s);
 }
@@ -737,49 +853,61 @@ pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
 }
 
 void
-pfi_fill_oldstatus(struct pf_status *pfs)
+pfi_update_status(const char *name, struct pf_status *pfs)
 {
 	struct pfi_kif		*p;
-	struct pfi_kif_cmp 	 key;
+	struct pfi_kif_cmp	 key;
+	struct ifg_member	 p_member, *ifgm;
+	TAILQ_HEAD(, ifg_member) ifg_members;
 	int			 i, j, k, s;
 
-	strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name));
+	strlcpy(key.pfik_name, name, sizeof(key.pfik_name));
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	p = RB_FIND(pfi_ifhead, &V_pfi_ifs, (struct pfi_kif *)&key);
+#else
 	p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key);
+#endif
 	if (p == NULL) {
 		splx(s);
 		return;
 	}
-	bzero(pfs->pcounters, sizeof(pfs->pcounters));
-	bzero(pfs->bcounters, sizeof(pfs->bcounters));
-	for (i = 0; i < 2; i++)
-		for (j = 0; j < 2; j++)
-			for (k = 0; k < 2; k++) {
-				pfs->pcounters[i][j][k] =
-					p->pfik_packets[i][j][k];
-				pfs->bcounters[i][j] +=
-					p->pfik_bytes[i][j][k];
-			}
-	splx(s);
-}
-
-int
-pfi_clr_istats(const char *name)
-{
-	struct pfi_kif	*p;
-	int		 s;
+	if (p->pfik_group != NULL) {
+		bcopy(&p->pfik_group->ifg_members, &ifg_members,
+		    sizeof(ifg_members));
+	} else {
+		/* build a temporary list for p only */
+		bzero(&p_member, sizeof(p_member));
+		p_member.ifgm_ifp = p->pfik_ifp;
+		TAILQ_INIT(&ifg_members);
+		TAILQ_INSERT_TAIL(&ifg_members, &p_member, ifgm_next);
+	}
+	if (pfs) {
+		bzero(pfs->pcounters, sizeof(pfs->pcounters));
+		bzero(pfs->bcounters, sizeof(pfs->bcounters));
+	}
+	TAILQ_FOREACH(ifgm, &ifg_members, ifgm_next) {
+		if (ifgm->ifgm_ifp == NULL)
+			continue;
+		p = (struct pfi_kif *)ifgm->ifgm_ifp->if_pf_kif;
 
-	s = splsoftnet();
-	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
-		if (pfi_skip_if(name, p))
+		/* just clear statistics */
+		if (pfs == NULL) {
+			bzero(p->pfik_packets, sizeof(p->pfik_packets));
+			bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
+			p->pfik_tzero = time_second;
 			continue;
-		bzero(p->pfik_packets, sizeof(p->pfik_packets));
-		bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
-		p->pfik_tzero = time_second;
+		}
+		for (i = 0; i < 2; i++)
+			for (j = 0; j < 2; j++)
+				for (k = 0; k < 2; k++) {
+					pfs->pcounters[i][j][k] +=
+						p->pfik_packets[i][j][k];
+					pfs->bcounters[i][j] +=
+						p->pfik_bytes[i][j][k];
+				}
 	}
 	splx(s);
-
-	return (0);
 }
 
 int
@@ -792,8 +920,13 @@ pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
 #endif
 
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	for (p = RB_MIN(pfi_ifhead, &V_pfi_ifs); p; p = nextp) {
+		nextp = RB_NEXT(pfi_ifhead, &V_pfi_ifs, p);
+#else
 	for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) {
 		nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
+#endif
 		if (pfi_skip_if(name, p))
 			continue;
 		if (*size > n++) {
@@ -810,7 +943,11 @@ pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
 				splx(s);
 				return (EFAULT);
 			}
+#ifdef __FreeBSD__
+			nextp = RB_NEXT(pfi_ifhead, &V_pfi_ifs, p);
+#else
 			nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
+#endif
 			pfi_kif_unref(p, PFI_KIF_REF_RULE);
 		}
 	}
@@ -845,7 +982,11 @@ pfi_set_flags(const char *name, int flags)
 	int		 s;
 
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	RB_FOREACH(p, pfi_ifhead, &V_pfi_ifs) {
+#else
 	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+#endif
 		if (pfi_skip_if(name, p))
 			continue;
 		p->pfik_flags |= flags;
@@ -861,7 +1002,11 @@ pfi_clear_flags(const char *name, int flags)
 	int		 s;
 
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	RB_FOREACH(p, pfi_ifhead, &V_pfi_ifs) {
+#else
 	RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+#endif
 		if (pfi_skip_if(name, p))
 			continue;
 		p->pfik_flags &= ~flags;
@@ -894,55 +1039,73 @@ pfi_unmask(void *addr)
 void
 pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp)
 {
+
+	CURVNET_SET(ifp->if_vnet);
 	PF_LOCK();
 	pfi_attach_ifnet(ifp);
 #ifdef ALTQ
 	pf_altq_ifnet_event(ifp, 0);
 #endif
 	PF_UNLOCK();
+	CURVNET_RESTORE();
 }
 
 void
 pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp)
 {
+
+	CURVNET_SET(ifp->if_vnet);
 	PF_LOCK();
 	pfi_detach_ifnet(ifp);
 #ifdef ALTQ
 	pf_altq_ifnet_event(ifp, 1);
 #endif
 	PF_UNLOCK();
+	CURVNET_RESTORE();
 }
 
 void
-pfi_attach_group_event(void *arg __unused, struct ifg_group *ifg)
+pfi_attach_group_event(void *arg , struct ifg_group *ifg)
 {
+
+	CURVNET_SET((struct vnet *)arg);
 	PF_LOCK();
 	pfi_attach_ifgroup(ifg);
 	PF_UNLOCK();
+	CURVNET_RESTORE();
 }
 
 void
-pfi_change_group_event(void *arg __unused, char *gname)
+pfi_change_group_event(void *arg, char *gname)
 {
+
+	CURVNET_SET((struct vnet *)arg);
 	PF_LOCK();
 	pfi_group_change(gname);
 	PF_UNLOCK();
+	CURVNET_RESTORE();
 }
 
 void
-pfi_detach_group_event(void *arg __unused, struct ifg_group *ifg)
+pfi_detach_group_event(void *arg, struct ifg_group *ifg)
 {
+
+	CURVNET_SET((struct vnet *)arg);
 	PF_LOCK();
 	pfi_detach_ifgroup(ifg);
 	PF_UNLOCK();
+	CURVNET_RESTORE();
 }
 
 void
 pfi_ifaddr_event(void *arg __unused, struct ifnet *ifp)
 {
+
+	CURVNET_SET(ifp->if_vnet);
 	PF_LOCK();
 	if (ifp && ifp->if_pf_kif)
 		pfi_kifaddr_update(ifp->if_pf_kif);
 	PF_UNLOCK();
+	CURVNET_RESTORE();
 }
 #endif /* __FreeBSD__ */
diff --git a/sys/contrib/pf/net/pf_ioctl.c b/sys/contrib/pf/net/pf_ioctl.c
index c41fcc6..2ca1630 100644
--- a/sys/contrib/pf/net/pf_ioctl.c
+++ b/sys/contrib/pf/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf_ioctl.c,v 1.175 2007/02/26 22:47:43 deraadt Exp $ */
+/*	$OpenBSD: pf_ioctl.c,v 1.213 2009/02/15 21:46:12 mbalmer Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -45,27 +45,26 @@ __FBSDID("$FreeBSD$");
 #include "opt_pf.h"
 
 #ifdef DEV_BPF
-#define	NBPFILTER	DEV_BPF
+#define		NBPFILTER	DEV_BPF
 #else
-#define	NBPFILTER	0
+#define		NBPFILTER	0
 #endif
 
 #ifdef DEV_PFLOG
-#define	NPFLOG		DEV_PFLOG
+#define		NPFLOG		DEV_PFLOG
 #else
-#define	NPFLOG		0
+#define		NPFLOG		0
 #endif
 
 #ifdef DEV_PFSYNC
-#define	NPFSYNC		DEV_PFSYNC
+#define		NPFSYNC		DEV_PFSYNC
 #else
-#define	NPFSYNC		0
+#define		NPFSYNC		0
 #endif
 
 #else
-#include "bpfilter.h"
-#include "pflog.h"
 #include "pfsync.h"
+#include "pflog.h"
 #endif
 
 #include 
@@ -77,8 +76,9 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
 #ifdef __FreeBSD__
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -100,6 +100,7 @@ __FBSDID("$FreeBSD$");
 #ifdef __FreeBSD__
 #include 
 #endif
+#include 
 
 #include 
 #include 
@@ -116,11 +117,11 @@ __FBSDID("$FreeBSD$");
 #endif
 #include 
 
-#if NPFSYNC > 0
 #include 
-#endif /* NPFSYNC > 0 */
 
+#if NPFLOG > 0
 #include 
+#endif /* NPFLOG > 0 */
 
 #ifdef INET6
 #include 
@@ -156,7 +157,7 @@ void			 pf_empty_pool(struct pf_palist *);
 #ifdef __FreeBSD__
 int			 pfioctl(struct cdev *, u_long, caddr_t, int, struct thread *);
 #else
-int			 pfioctl(struct cdev *, u_long, caddr_t, int, struct proc *);
+int			 pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
 #endif
 #ifdef ALTQ
 int			 pf_begin_altq(u_int32_t *);
@@ -171,25 +172,43 @@ int			 pf_setup_pfsync_matching(struct pf_ruleset *);
 void			 pf_hash_rule(MD5_CTX *, struct pf_rule *);
 void			 pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
 int			 pf_commit_rules(u_int32_t, int, char *);
+int			 pf_addr_setup(struct pf_ruleset *,
+			    struct pf_addr_wrap *, sa_family_t);
+void			 pf_addr_copyout(struct pf_addr_wrap *);
+
+#define	TAGID_MAX	 50000
 
-struct pf_rule		 pf_default_rule;
 #ifdef __FreeBSD__
-struct sx		 pf_consistency_lock;
-SX_SYSINIT(pf_consistency_lock, &pf_consistency_lock, "pf_statetbl_lock");
-#else
-struct rwlock		 pf_consistency_lock = RWLOCK_INITIALIZER;
+VNET_DEFINE(struct pf_rule,	 pf_default_rule);
+VNET_DEFINE(struct sx,		 pf_consistency_lock);
+
+#ifdef ALTQ
+static VNET_DEFINE(int,		pf_altq_running);
+#define	V_pf_altq_running	VNET(pf_altq_running)
 #endif
+
+TAILQ_HEAD(pf_tags, pf_tagname);
+
+#define	V_pf_tags		VNET(pf_tags)
+VNET_DEFINE(struct pf_tags, pf_tags);
+#define	V_pf_qids		VNET(pf_qids)
+VNET_DEFINE(struct pf_tags, pf_qids);
+
+#else /* !__FreeBSD__ */
+struct pf_rule		 pf_default_rule;
+struct rwlock		 pf_consistency_lock = RWLOCK_INITIALIZER("pfcnslk");
 #ifdef ALTQ
 static int		 pf_altq_running;
 #endif
 
-#define	TAGID_MAX	 50000
 TAILQ_HEAD(pf_tags, pf_tagname)	pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
 				pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
+#endif /* __FreeBSD__ */
 
 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
 #endif
+
 u_int16_t		 tagname2tag(struct pf_tags *, char *);
 void			 tag2tagname(struct pf_tags *, u_int16_t, char *);
 void			 tag_unref(struct pf_tags *, u_int16_t);
@@ -197,12 +216,15 @@ int			 pf_rtlabel_add(struct pf_addr_wrap *);
 void			 pf_rtlabel_remove(struct pf_addr_wrap *);
 void			 pf_rtlabel_copyout(struct pf_addr_wrap *);
 
+#ifdef __FreeBSD__
+#define DPFPRINTF(n, x) if (V_pf_status.debug >= (n)) printf x
+#else
 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
-
+#endif
 
 #ifdef __FreeBSD__
-static struct cdev	*pf_dev;
-
+struct cdev *pf_dev;
+ 
 /*
  * XXX - These are new and need to be checked when moveing to a new version
  */
@@ -218,22 +240,22 @@ static void		 pf_clear_srcnodes(void);
  */
 #ifdef INET
 static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
-		int dir, struct inpcb *inp);
+    int dir, struct inpcb *inp);
 static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
-		int dir, struct inpcb *inp);
+    int dir, struct inpcb *inp);
 #endif
 #ifdef INET6
 static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
-		int dir, struct inpcb *inp);
+    int dir, struct inpcb *inp);
 static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
-		int dir, struct inpcb *inp);
+    int dir, struct inpcb *inp);
 #endif
-
-static int 		 hook_pf(void);
-static int 		 dehook_pf(void);
-static int 		 shutdown_pf(void);
-static int 		 pf_load(void);
-static int 		 pf_unload(void);
+ 
+static int		hook_pf(void);
+static int		dehook_pf(void);
+static int		shutdown_pf(void);
+static int		pf_load(void);
+static int		pf_unload(void);
 
 static struct cdevsw pf_cdevsw = {
 	.d_ioctl =	pfioctl,
@@ -241,78 +263,97 @@ static struct cdevsw pf_cdevsw = {
 	.d_version =	D_VERSION,
 };
 
-static volatile int pf_pfil_hooked = 0;
-int pf_end_threads = 0;
-struct mtx pf_task_mtx;
-pflog_packet_t *pflog_packet_ptr = NULL;
-
-int debug_pfugidhack = 0;
-SYSCTL_INT(_debug, OID_AUTO, pfugidhack, CTLFLAG_RW, &debug_pfugidhack, 0,
-    "Enable/disable pf user/group rules mpsafe hack");
+static volatile VNET_DEFINE(int, pf_pfil_hooked);
+#define V_pf_pfil_hooked	VNET(pf_pfil_hooked)
+VNET_DEFINE(int,		pf_end_threads);
+VNET_DEFINE(struct mtx,		pf_task_mtx);
+
+/* pfsync */
+pfsync_state_import_t 		*pfsync_state_import_ptr = NULL;
+pfsync_insert_state_t		*pfsync_insert_state_ptr = NULL;
+pfsync_update_state_t		*pfsync_update_state_ptr = NULL;
+pfsync_delete_state_t		*pfsync_delete_state_ptr = NULL;
+pfsync_clear_states_t		*pfsync_clear_states_ptr = NULL;
+pfsync_state_in_use_t		*pfsync_state_in_use_ptr = NULL;
+pfsync_defer_t			*pfsync_defer_ptr = NULL;
+pfsync_up_t			*pfsync_up_ptr = NULL;
+/* pflow */
+export_pflow_t			*export_pflow_ptr = NULL;
+/* pflog */
+pflog_packet_t			*pflog_packet_ptr = NULL;
+
+VNET_DEFINE(int, debug_pfugidhack);
+SYSCTL_VNET_INT(_debug, OID_AUTO, pfugidhack, CTLFLAG_RW,
+	&VNET_NAME(debug_pfugidhack), 0,
+	"Enable/disable pf user/group rules mpsafe hack");
 
 void
 init_pf_mutex(void)
 {
-	mtx_init(&pf_task_mtx, "pf task mtx", NULL, MTX_DEF);
+
+	mtx_init(&V_pf_task_mtx, "pf task mtx", NULL, MTX_DEF);
 }
 
 void
 destroy_pf_mutex(void)
 {
-	mtx_destroy(&pf_task_mtx);
-}
 
+	mtx_destroy(&V_pf_task_mtx);
+}
 void
 init_zone_var(void)
 {
-	pf_src_tree_pl = pf_rule_pl = NULL;
-	pf_state_pl = pf_altq_pl = pf_pooladdr_pl = NULL;
-	pf_frent_pl = pf_frag_pl = pf_cache_pl = pf_cent_pl = NULL;
-	pf_state_scrub_pl = NULL;
-	pfr_ktable_pl = pfr_kentry_pl = NULL;
+	V_pf_src_tree_pl = V_pf_rule_pl = NULL;
+	V_pf_state_pl = V_pf_state_key_pl = V_pf_state_item_pl = NULL;
+	V_pf_altq_pl = V_pf_pooladdr_pl = NULL;
+	V_pf_frent_pl = V_pf_frag_pl = V_pf_cache_pl = V_pf_cent_pl = NULL;
+	V_pf_state_scrub_pl = NULL;
+	V_pfr_ktable_pl = V_pfr_kentry_pl = NULL;
 }
 
 void
 cleanup_pf_zone(void)
 {
-	UMA_DESTROY(pf_src_tree_pl);
-	UMA_DESTROY(pf_rule_pl);
-	UMA_DESTROY(pf_state_pl);
-	UMA_DESTROY(pf_altq_pl);
-	UMA_DESTROY(pf_pooladdr_pl);
-	UMA_DESTROY(pf_frent_pl);
-	UMA_DESTROY(pf_frag_pl);
-	UMA_DESTROY(pf_cache_pl);
-	UMA_DESTROY(pf_cent_pl);
-	UMA_DESTROY(pfr_ktable_pl);
-	UMA_DESTROY(pfr_kentry_pl2);
-	UMA_DESTROY(pfr_kentry_pl);
-	UMA_DESTROY(pf_state_scrub_pl);
-	UMA_DESTROY(pfi_addr_pl);
+	UMA_DESTROY(V_pf_src_tree_pl);
+	UMA_DESTROY(V_pf_rule_pl);
+	UMA_DESTROY(V_pf_state_pl);
+	UMA_DESTROY(V_pf_state_key_pl);
+	UMA_DESTROY(V_pf_state_item_pl);
+	UMA_DESTROY(V_pf_altq_pl);
+	UMA_DESTROY(V_pf_pooladdr_pl);
+	UMA_DESTROY(V_pf_frent_pl);
+	UMA_DESTROY(V_pf_frag_pl);
+	UMA_DESTROY(V_pf_cache_pl);
+	UMA_DESTROY(V_pf_cent_pl);
+	UMA_DESTROY(V_pfr_ktable_pl);
+	UMA_DESTROY(V_pfr_kentry_pl);
+	UMA_DESTROY(V_pf_state_scrub_pl);
+	UMA_DESTROY(V_pfi_addr_pl);
 }
 
 int
 pfattach(void)
 {
-	u_int32_t *my_timeout = pf_default_rule.timeout;
+	u_int32_t *my_timeout = V_pf_default_rule.timeout;
 	int error = 1;
 
 	do {
-		UMA_CREATE(pf_src_tree_pl,struct pf_src_node, "pfsrctrpl");
-		UMA_CREATE(pf_rule_pl,	  struct pf_rule, "pfrulepl");
-		UMA_CREATE(pf_state_pl,	  struct pf_state, "pfstatepl");
-		UMA_CREATE(pf_altq_pl,	  struct pf_altq, "pfaltqpl");
-		UMA_CREATE(pf_pooladdr_pl, struct pf_pooladdr, "pfpooladdrpl");
-		UMA_CREATE(pfr_ktable_pl,  struct pfr_ktable, "pfrktable");
-		UMA_CREATE(pfr_kentry_pl,  struct pfr_kentry, "pfrkentry");
-		UMA_CREATE(pfr_kentry_pl2,  struct pfr_kentry, "pfrkentry2");
-		UMA_CREATE(pf_frent_pl,	  struct pf_frent, "pffrent");
-		UMA_CREATE(pf_frag_pl,	  struct pf_fragment, "pffrag");
-		UMA_CREATE(pf_cache_pl,	  struct pf_fragment, "pffrcache");
-		UMA_CREATE(pf_cent_pl,	  struct pf_frcache, "pffrcent");
-		UMA_CREATE(pf_state_scrub_pl, struct pf_state_scrub, 
+		UMA_CREATE(V_pf_src_tree_pl,	struct pf_src_node, "pfsrctrpl");
+		UMA_CREATE(V_pf_rule_pl,	struct pf_rule, "pfrulepl");
+		UMA_CREATE(V_pf_state_pl,	struct pf_state, "pfstatepl");
+		UMA_CREATE(V_pf_state_key_pl,	struct pf_state, "pfstatekeypl");
+		UMA_CREATE(V_pf_state_item_pl,	struct pf_state, "pfstateitempl");
+		UMA_CREATE(V_pf_altq_pl,	struct pf_altq, "pfaltqpl");
+		UMA_CREATE(V_pf_pooladdr_pl,	struct pf_pooladdr, "pfpooladdrpl");
+		UMA_CREATE(V_pfr_ktable_pl,	struct pfr_ktable, "pfrktable");
+		UMA_CREATE(V_pfr_kentry_pl,	struct pfr_kentry, "pfrkentry");
+		UMA_CREATE(V_pf_frent_pl,	struct pf_frent, "pffrent");
+		UMA_CREATE(V_pf_frag_pl,	struct pf_fragment, "pffrag");
+		UMA_CREATE(V_pf_cache_pl,	struct pf_fragment, "pffrcache");
+		UMA_CREATE(V_pf_cent_pl,	struct pf_frcache, "pffrcent");
+		UMA_CREATE(V_pf_state_scrub_pl,	struct pf_state_scrub, 
 		    "pfstatescrub");
-		UMA_CREATE(pfi_addr_pl, struct pfi_dynaddr, "pfiaddrpl");
+		UMA_CREATE(V_pfi_addr_pl,	struct pfi_dynaddr, "pfiaddrpl");
 		error = 0;
 	} while(0);
 	if (error) {
@@ -327,34 +368,35 @@ pfattach(void)
 		return (error);
 	}
 
-	pf_pool_limits[PF_LIMIT_STATES].pp = pf_state_pl;
-	pf_pool_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
-	pf_pool_limits[PF_LIMIT_SRC_NODES].pp = pf_src_tree_pl;
-	pf_pool_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
-	pf_pool_limits[PF_LIMIT_FRAGS].pp = pf_frent_pl;
-	pf_pool_limits[PF_LIMIT_FRAGS].limit = PFFRAG_FRENT_HIWAT;
-	pf_pool_limits[PF_LIMIT_TABLES].pp = pfr_ktable_pl;
-	pf_pool_limits[PF_LIMIT_TABLES].limit = PFR_KTABLE_HIWAT;
-	pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].pp = pfr_kentry_pl;
-	pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT;
-	uma_zone_set_max(pf_pool_limits[PF_LIMIT_STATES].pp,
-		pf_pool_limits[PF_LIMIT_STATES].limit);
-
-	RB_INIT(&tree_src_tracking);
-	RB_INIT(&pf_anchors);
+	V_pf_pool_limits[PF_LIMIT_STATES].pp = V_pf_state_pl;
+	V_pf_pool_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
+	V_pf_pool_limits[PF_LIMIT_SRC_NODES].pp = V_pf_src_tree_pl;
+	V_pf_pool_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
+	V_pf_pool_limits[PF_LIMIT_FRAGS].pp = V_pf_frent_pl;
+	V_pf_pool_limits[PF_LIMIT_FRAGS].limit = PFFRAG_FRENT_HIWAT;
+	V_pf_pool_limits[PF_LIMIT_TABLES].pp = V_pfr_ktable_pl;
+	V_pf_pool_limits[PF_LIMIT_TABLES].limit = PFR_KTABLE_HIWAT;
+	V_pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].pp = V_pfr_kentry_pl;
+	V_pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT;
+	uma_zone_set_max(V_pf_pool_limits[PF_LIMIT_STATES].pp,
+	    V_pf_pool_limits[PF_LIMIT_STATES].limit);
+
+	RB_INIT(&V_tree_src_tracking);
+	RB_INIT(&V_pf_anchors);
 	pf_init_ruleset(&pf_main_ruleset);
-	TAILQ_INIT(&pf_altqs[0]);
-	TAILQ_INIT(&pf_altqs[1]);
-	TAILQ_INIT(&pf_pabuf);
-	pf_altqs_active = &pf_altqs[0];
-	pf_altqs_inactive = &pf_altqs[1];
-	TAILQ_INIT(&state_list);
+
+	TAILQ_INIT(&V_pf_altqs[0]);
+	TAILQ_INIT(&V_pf_altqs[1]);
+	TAILQ_INIT(&V_pf_pabuf);
+	V_pf_altqs_active = &V_pf_altqs[0];
+	V_pf_altqs_inactive = &V_pf_altqs[1];
+	TAILQ_INIT(&V_state_list);
 
 	/* default rule should never be garbage collected */
-	pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
-	pf_default_rule.action = PF_PASS;
-	pf_default_rule.nr = -1;
-	pf_default_rule.rtableid = -1;
+	V_pf_default_rule.entries.tqe_prev = &V_pf_default_rule.entries.tqe_next;
+	V_pf_default_rule.action = PF_PASS;
+	V_pf_default_rule.nr = -1;
+	V_pf_default_rule.rtableid = -1;
 
 	/* initialize default timeouts */
 	my_timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
@@ -379,20 +421,24 @@ pfattach(void)
 	my_timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
 
 	pf_normalize_init();
-	bzero(&pf_status, sizeof(pf_status));
-	pf_status.debug = PF_DEBUG_URGENT;
 
-	pf_pfil_hooked = 0;
+	bzero(&V_pf_status, sizeof(V_pf_status));
+	V_pf_status.debug = PF_DEBUG_URGENT;
+
+	V_pf_pfil_hooked = 0;
 
 	/* XXX do our best to avoid a conflict */
-	pf_status.hostid = arc4random();
+	V_pf_status.hostid = arc4random();
 
-	if (kproc_create(pf_purge_thread, NULL, NULL, 0, 0, "pfpurge"))
+	if (kproc_create(pf_purge_thread, curvnet, NULL, 0, 0, "pfpurge"))
 		return (ENXIO);
 
+	m_addr_chg_pf_p = pf_pkt_addr_changed;
+
 	return (error);
 }
 #else /* !__FreeBSD__ */
+
 void
 pfattach(int num)
 {
@@ -404,6 +450,10 @@ pfattach(int num)
 	    "pfsrctrpl", NULL);
 	pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
 	    NULL);
+	pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0, 0, 0,
+	    "pfstatekeypl", NULL);
+	pool_init(&pf_state_item_pl, sizeof(struct pf_state_item), 0, 0, 0,
+	    "pfstateitempl", NULL);
 	pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
 	    &pool_allocator_nointr);
 	pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
@@ -415,7 +465,7 @@ pfattach(int num)
 	pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
 	    pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
 
-	if (ctob(physmem) <= 100*1024*1024)
+	if (physmem <= atop(100*1024*1024))
 		pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
 		    PFR_KENTRY_HIWAT_SMALL;
 
@@ -465,32 +515,32 @@ pfattach(int num)
 	pf_status.hostid = arc4random();
 
 	/* require process context to purge states, so perform in a thread */
-	kproc_create_deferred(pf_thread_create, NULL);
+	kthread_create_deferred(pf_thread_create, NULL);
 }
 
 void
 pf_thread_create(void *v)
 {
-	if (kproc_create(pf_purge_thread, NULL, NULL, "pfpurge"))
+	if (kthread_create(pf_purge_thread, NULL, NULL, "pfpurge"))
 		panic("pfpurge thread");
 }
 
 int
-pfopen(struct cdev *dev, int flags, int fmt, struct proc *p)
+pfopen(dev_t dev, int flags, int fmt, struct proc *p)
 {
-	if (dev2unit(dev) >= 1)
+	if (minor(dev) >= 1)
 		return (ENXIO);
 	return (0);
 }
 
 int
-pfclose(struct cdev *dev, int flags, int fmt, struct proc *p)
+pfclose(dev_t dev, int flags, int fmt, struct proc *p)
 {
-	if (dev2unit(dev) >= 1)
+	if (minor(dev) >= 1)
 		return (ENXIO);
 	return (0);
 }
-#endif /* __FreeBSD__ */
+#endif
 
 struct pf_pool *
 pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
@@ -557,7 +607,11 @@ pf_empty_pool(struct pf_palist *poola)
 		pf_tbladdr_remove(&empty_pool_pa->addr);
 		pfi_kif_unref(empty_pool_pa->kif, PFI_KIF_REF_RULE);
 		TAILQ_REMOVE(poola, empty_pool_pa, entries);
+#ifdef __FreeBSD__
+		pool_put(&V_pf_pooladdr_pl, empty_pool_pa);
+#else
 		pool_put(&pf_pooladdr_pl, empty_pool_pa);
+#endif
 	}
 }
 
@@ -565,7 +619,7 @@ void
 pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
 {
 	if (rulequeue != NULL) {
-		if (rule->states <= 0) {
+		if (rule->states_cur <= 0) {
 			/*
 			 * XXX - we need to remove the table *before* detaching
 			 * the rule to make sure the table code does not delete
@@ -581,7 +635,7 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
 		rule->nr = -1;
 	}
 
-	if (rule->states > 0 || rule->src_nodes > 0 ||
+	if (rule->states_cur > 0 || rule->src_nodes > 0 ||
 	    rule->entries.tqe_prev != NULL)
 		return;
 	pf_tag_unref(rule->tag);
@@ -604,7 +658,11 @@ pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
 	pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
 	pf_anchor_remove(rule);
 	pf_empty_pool(&rule->rpool.list);
+#ifdef __FreeBSD__
+	pool_put(&V_pf_rule_pl, rule);
+#else
 	pool_put(&pf_rule_pl, rule);
+#endif
 }
 
 u_int16_t
@@ -635,11 +693,9 @@ tagname2tag(struct pf_tags *head, char *tagname)
 		return (0);
 
 	/* allocate and fill new struct pf_tagname */
-	tag = (struct pf_tagname *)malloc(sizeof(struct pf_tagname),
-	    M_TEMP, M_NOWAIT);
+	tag = malloc(sizeof(*tag), M_TEMP, M_NOWAIT|M_ZERO);
 	if (tag == NULL)
 		return (0);
-	bzero(tag, sizeof(struct pf_tagname));
 	strlcpy(tag->name, tagname, sizeof(tag->name));
 	tag->tag = new_tagid;
 	tag->ref++;
@@ -687,13 +743,21 @@ tag_unref(struct pf_tags *head, u_int16_t tag)
 u_int16_t
 pf_tagname2tag(char *tagname)
 {
+#ifdef __FreeBSD__
+	return (tagname2tag(&V_pf_tags, tagname));
+#else
 	return (tagname2tag(&pf_tags, tagname));
+#endif
 }
 
 void
 pf_tag2tagname(u_int16_t tagid, char *p)
 {
+#ifdef __FreeBSD__
+	tag2tagname(&V_pf_tags, tagid, p);
+#else
 	tag2tagname(&pf_tags, tagid, p);
+#endif
 }
 
 void
@@ -701,7 +765,11 @@ pf_tag_ref(u_int16_t tag)
 {
 	struct pf_tagname *t;
 
+#ifdef __FreeBSD__
+	TAILQ_FOREACH(t, &V_pf_tags, entries)
+#else
 	TAILQ_FOREACH(t, &pf_tags, entries)
+#endif
 		if (t->tag == tag)
 			break;
 	if (t != NULL)
@@ -711,7 +779,11 @@ pf_tag_ref(u_int16_t tag)
 void
 pf_tag_unref(u_int16_t tag)
 {
+#ifdef __FreeBSD__
+	tag_unref(&V_pf_tags, tag);
+#else
 	tag_unref(&pf_tags, tag);
+#endif
 }
 
 int
@@ -764,19 +836,31 @@ pf_rtlabel_copyout(struct pf_addr_wrap *a)
 u_int32_t
 pf_qname2qid(char *qname)
 {
+#ifdef __FreeBSD__
+	return ((u_int32_t)tagname2tag(&V_pf_qids, qname));
+#else
 	return ((u_int32_t)tagname2tag(&pf_qids, qname));
+#endif
 }
 
 void
 pf_qid2qname(u_int32_t qid, char *p)
 {
+#ifdef __FreeBSD__
+	tag2tagname(&V_pf_qids, (u_int16_t)qid, p);
+#else
 	tag2tagname(&pf_qids, (u_int16_t)qid, p);
+#endif
 }
 
 void
 pf_qid_unref(u_int32_t qid)
 {
+#ifdef __FreeBSD__
+	tag_unref(&V_pf_qids, (u_int16_t)qid);
+#else
 	tag_unref(&pf_qids, (u_int16_t)qid);
+#endif
 }
 
 int
@@ -786,24 +870,35 @@ pf_begin_altq(u_int32_t *ticket)
 	int		 error = 0;
 
 	/* Purge the old altq list */
-	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
-		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
 #ifdef __FreeBSD__
+	while ((altq = TAILQ_FIRST(V_pf_altqs_inactive)) != NULL) {
+		TAILQ_REMOVE(V_pf_altqs_inactive, altq, entries);
 		if (altq->qname[0] == 0 &&
 		    (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
 #else
+	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
 		if (altq->qname[0] == 0) {
 #endif
 			/* detach and destroy the discipline */
 			error = altq_remove(altq);
 		} else
 			pf_qid_unref(altq->qid);
+#ifdef __FreeBSD__
+		pool_put(&V_pf_altq_pl, altq);
+#else
 		pool_put(&pf_altq_pl, altq);
+#endif
 	}
 	if (error)
 		return (error);
+#ifdef __FreeBSD__
+	*ticket = ++V_ticket_altqs_inactive;
+	V_altqs_inactive_open = 1;
+#else
 	*ticket = ++ticket_altqs_inactive;
 	altqs_inactive_open = 1;
+#endif
 	return (0);
 }
 
@@ -813,24 +908,37 @@ pf_rollback_altq(u_int32_t ticket)
 	struct pf_altq	*altq;
 	int		 error = 0;
 
+#ifdef __FreeBSD__
+	if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
+		return (0);
+	/* Purge the old altq list */
+	while ((altq = TAILQ_FIRST(V_pf_altqs_inactive)) != NULL) {
+		TAILQ_REMOVE(V_pf_altqs_inactive, altq, entries);
+		if (altq->qname[0] == 0 &&
+		   (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
 	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
 		return (0);
 	/* Purge the old altq list */
 	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
 		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
-#ifdef __FreeBSD__
-		if (altq->qname[0] == 0 &&
-		    (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
-#else
 		if (altq->qname[0] == 0) {
 #endif
 			/* detach and destroy the discipline */
 			error = altq_remove(altq);
 		} else
 			pf_qid_unref(altq->qid);
+#ifdef __FreeBSD__
+		pool_put(&V_pf_altq_pl, altq);
+#else
 		pool_put(&pf_altq_pl, altq);
+#endif
 	}
+#ifdef __FreeBSD__
+	V_altqs_inactive_open = 0;
+#else
 	altqs_inactive_open = 0;
+#endif
 	return (error);
 }
 
@@ -841,27 +949,43 @@ pf_commit_altq(u_int32_t ticket)
 	struct pf_altq		*altq;
 	int			 s, err, error = 0;
 
+#ifdef __FreeBSD__
+	if (!V_altqs_inactive_open || ticket != V_ticket_altqs_inactive)
+#else
 	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
+#endif
 		return (EBUSY);
 
 	/* swap altqs, keep the old. */
 	s = splsoftnet();
+#ifdef __FreeBSD__
+	old_altqs = V_pf_altqs_active;
+	V_pf_altqs_active = V_pf_altqs_inactive;
+	V_pf_altqs_inactive = old_altqs;
+	V_ticket_altqs_active = V_ticket_altqs_inactive;
+#else
 	old_altqs = pf_altqs_active;
 	pf_altqs_active = pf_altqs_inactive;
 	pf_altqs_inactive = old_altqs;
 	ticket_altqs_active = ticket_altqs_inactive;
+#endif
 
 	/* Attach new disciplines */
-	TAILQ_FOREACH(altq, pf_altqs_active, entries) {
 #ifdef __FreeBSD__
-		if (altq->qname[0] == 0 &&
-		    (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+	TAILQ_FOREACH(altq, V_pf_altqs_active, entries) {
+	if (altq->qname[0] == 0 &&
+	   (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
 #else
+	TAILQ_FOREACH(altq, pf_altqs_active, entries) {
 		if (altq->qname[0] == 0) {
 #endif
 			/* attach the discipline */
 			error = altq_pfattach(altq);
+#ifdef __FreeBSD__
+			if (error == 0 && V_pf_altq_running)
+#else
 			if (error == 0 && pf_altq_running)
+#endif
 				error = pf_enable_altq(altq);
 			if (error != 0) {
 				splx(s);
@@ -871,16 +995,22 @@ pf_commit_altq(u_int32_t ticket)
 	}
 
 	/* Purge the old altq list */
-	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
-		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
 #ifdef __FreeBSD__
+	while ((altq = TAILQ_FIRST(V_pf_altqs_inactive)) != NULL) {
+		TAILQ_REMOVE(V_pf_altqs_inactive, altq, entries);
 		if (altq->qname[0] == 0 &&
 		    (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
 #else
+	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
 		if (altq->qname[0] == 0) {
 #endif
 			/* detach and destroy the discipline */
+#ifdef __FreeBSD__
+			if (V_pf_altq_running)
+#else
 			if (pf_altq_running)
+#endif
 				error = pf_disable_altq(altq);
 			err = altq_pfdetach(altq);
 			if (err != 0 && error == 0)
@@ -890,11 +1020,19 @@ pf_commit_altq(u_int32_t ticket)
 				error = err;
 		} else
 			pf_qid_unref(altq->qid);
+#ifdef __FreeBSD__
+		pool_put(&V_pf_altq_pl, altq);
+#else
 		pool_put(&pf_altq_pl, altq);
+#endif
 	}
 	splx(s);
 
+#ifdef __FreeBSD__
+	V_altqs_inactive_open = 0;
+#else
 	altqs_inactive_open = 0;
+#endif
 	return (error);
 }
 
@@ -969,22 +1107,32 @@ pf_disable_altq(struct pf_altq *altq)
 void
 pf_altq_ifnet_event(struct ifnet *ifp, int remove)
 {
-	struct ifnet		*ifp1;
-	struct pf_altq		*a1, *a2, *a3;
-	u_int32_t		 ticket;
-	int			 error = 0;
+	struct ifnet	*ifp1;
+	struct pf_altq	*a1, *a2, *a3;
+	u_int32_t	 ticket;
+	int		 error = 0;
 
 	/* Interrupt userland queue modifications */
+#ifdef __FreeBSD__
+	if (V_altqs_inactive_open)
+		pf_rollback_altq(V_ticket_altqs_inactive);
+#else
 	if (altqs_inactive_open)
 		pf_rollback_altq(ticket_altqs_inactive);
+#endif
 
 	/* Start new altq ruleset */
 	if (pf_begin_altq(&ticket))
 		return;
 
 	/* Copy the current active set */
+#ifdef __FreeBSD__
+	TAILQ_FOREACH(a1, V_pf_altqs_active, entries) {
+		a2 = pool_get(&V_pf_altq_pl, PR_NOWAIT);
+#else
 	TAILQ_FOREACH(a1, pf_altqs_active, entries) {
 		a2 = pool_get(&pf_altq_pl, PR_NOWAIT);
+#endif
 		if (a2 == NULL) {
 			error = ENOMEM;
 			break;
@@ -994,11 +1142,19 @@ pf_altq_ifnet_event(struct ifnet *ifp, int remove)
 		if (a2->qname[0] != 0) {
 			if ((a2->qid = pf_qname2qid(a2->qname)) == 0) {
 				error = EBUSY;
+#ifdef __FreeBSD__
+				pool_put(&V_pf_altq_pl, a2);
+#else
 				pool_put(&pf_altq_pl, a2);
+#endif
 				break;
 			}
 			a2->altq_disc = NULL;
+#ifdef __FreeBSD__
+			TAILQ_FOREACH(a3, V_pf_altqs_inactive, entries) {
+#else
 			TAILQ_FOREACH(a3, pf_altqs_inactive, entries) {
+#endif
 				if (strncmp(a3->ifname, a2->ifname,
 				    IFNAMSIZ) == 0 && a3->qname[0] == 0) {
 					a2->altq_disc = a3->altq_disc;
@@ -1016,23 +1172,35 @@ pf_altq_ifnet_event(struct ifnet *ifp, int remove)
 			error = altq_add(a2);
 			PF_LOCK();
 
+#ifdef __FreeBSD__
+			if (ticket != V_ticket_altqs_inactive)
+#else
 			if (ticket != ticket_altqs_inactive)
+#endif
 				error = EBUSY;
 
 			if (error) {
+#ifdef __FreeBSD__
+				pool_put(&V_pf_altq_pl, a2);
+#else
 				pool_put(&pf_altq_pl, a2);
+#endif
 				break;
 			}
 		}
 
+#ifdef __FreeBSD__
+		TAILQ_INSERT_TAIL(V_pf_altqs_inactive, a2, entries);
+#else
 		TAILQ_INSERT_TAIL(pf_altqs_inactive, a2, entries);
+#endif
 	}
 
 	if (error != 0)
 		pf_rollback_altq(ticket);
 	else
 		pf_commit_altq(ticket);
-}
+	}
 #endif
 #endif /* ALTQ */
 
@@ -1252,10 +1420,33 @@ pf_setup_pfsync_matching(struct pf_ruleset *rs)
 	}
 
 	MD5Final(digest, &ctx);
+#ifdef __FreeBSD__
+	memcpy(V_pf_status.pf_chksum, digest, sizeof(V_pf_status.pf_chksum));
+#else
 	memcpy(pf_status.pf_chksum, digest, sizeof(pf_status.pf_chksum));
+#endif
+	return (0);
+}
+
+int
+pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr,
+    sa_family_t af)
+{
+	if (pfi_dynaddr_setup(addr, af) ||
+	    pf_tbladdr_setup(ruleset, addr))
+		return (EINVAL);
+
 	return (0);
 }
 
+void
+pf_addr_copyout(struct pf_addr_wrap *addr)
+{
+	pfi_dynaddr_copyout(addr);
+	pf_tbladdr_copyout(addr);
+	pf_rtlabel_copyout(addr);
+}
+
 int
 #ifdef __FreeBSD__
 pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
@@ -1270,6 +1461,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 #endif
 	int			 error = 0;
 
+	CURVNET_SET(TD_TO_VNET(td));
+
 	/* XXX keep in sync with switch() below */
 #ifdef __FreeBSD__
 	if (securelevel_gt(td->td_ucred, 2))
@@ -1373,7 +1566,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			}
 			return (EACCES);
 		case DIOCGETRULE:
-			if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR)
+			if (((struct pfioc_rule *)addr)->action ==
+			    PF_GET_CLR_CNTR)
 				return (EACCES);
 			break;
 		default:
@@ -1382,9 +1576,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 
 	if (flags & FWRITE)
 #ifdef __FreeBSD__
-		sx_xlock(&pf_consistency_lock);
+		sx_xlock(&V_pf_consistency_lock);
 	else
-		sx_slock(&pf_consistency_lock);
+		sx_slock(&V_pf_consistency_lock);
 #else
 		rw_enter_write(&pf_consistency_lock);
 	else
@@ -1399,7 +1593,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 	switch (cmd) {
 
 	case DIOCSTART:
+#ifdef __FreeBSD__
+		if (V_pf_status.running)
+#else
 		if (pf_status.running)
+#endif
 			error = EEXIST;
 		else {
 #ifdef __FreeBSD__
@@ -1411,33 +1609,48 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 				    ("pf: pfil registeration fail\n"));
 				break;
 			}
-#endif
+			V_pf_status.running = 1;
+			V_pf_status.since = time_second;
+
+			if (V_pf_status.stateid == 0) {
+				V_pf_status.stateid = time_second;
+				V_pf_status.stateid = V_pf_status.stateid << 32;
+			}
+#else
 			pf_status.running = 1;
 			pf_status.since = time_second;
+
 			if (pf_status.stateid == 0) {
 				pf_status.stateid = time_second;
 				pf_status.stateid = pf_status.stateid << 32;
 			}
+#endif
 			DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
 		}
 		break;
 
 	case DIOCSTOP:
-		if (!pf_status.running)
+#ifdef __FreeBSD__
+		if (!V_pf_status.running)
 			error = ENOENT;
 		else {
-			pf_status.running = 0;
-#ifdef __FreeBSD__
+			V_pf_status.running = 0;
 			PF_UNLOCK();
 			error = dehook_pf();
 			PF_LOCK();
 			if (error) {
-				pf_status.running = 1;
+				V_pf_status.running = 1;
 				DPFPRINTF(PF_DEBUG_MISC,
-					("pf: pfil unregisteration failed\n"));
+				    ("pf: pfil unregisteration failed\n"));
 			}
-#endif
+			V_pf_status.since = time_second;
+#else
+		if (!pf_status.running)
+			error = ENOENT;
+		else {
+			pf_status.running = 0;
 			pf_status.since = time_second;
+#endif
 			DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
 		}
 		break;
@@ -1473,16 +1686,22 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			error = EBUSY;
 			break;
 		}
-		if (pr->pool_ticket != ticket_pabuf) {
 #ifdef __FreeBSD__
+		if (pr->pool_ticket != V_ticket_pabuf) {
 			DPFPRINTF(PF_DEBUG_MISC,
 			    ("pool_ticket: %d != %d\n", pr->pool_ticket,
-			    ticket_pabuf));
+			    V_ticket_pabuf));
+#else
+		if (pr->pool_ticket != ticket_pabuf) {
 #endif
 			error = EBUSY;
 			break;
 		}
-		rule = pool_get(&pf_rule_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+		rule = pool_get(&V_pf_rule_pl, PR_NOWAIT);
+#else
+		rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL);
+#endif
 		if (rule == NULL) {
 			error = ENOMEM;
 			break;
@@ -1499,19 +1718,27 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		rule->kif = NULL;
 		TAILQ_INIT(&rule->rpool.list);
 		/* initialize refcounting */
-		rule->states = 0;
+		rule->states_cur = 0;
 		rule->src_nodes = 0;
 		rule->entries.tqe_prev = NULL;
 #ifndef INET
 		if (rule->af == AF_INET) {
+#ifdef __FreeBSD__
+			pool_put(&V_pf_rule_pl, rule);
+#else
 			pool_put(&pf_rule_pl, rule);
+#endif
 			error = EAFNOSUPPORT;
 			break;
 		}
 #endif /* INET */
 #ifndef INET6
 		if (rule->af == AF_INET6) {
+#ifdef __FreeBSD__
+			pool_put(&V_pf_rule_pl, rule);
+#else
 			pool_put(&pf_rule_pl, rule);
+#endif
 			error = EAFNOSUPPORT;
 			break;
 		}
@@ -1525,7 +1752,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		if (rule->ifname[0]) {
 			rule->kif = pfi_kif_get(rule->ifname);
 			if (rule->kif == NULL) {
+#ifdef __FreeBSD__
+				pool_put(&V_pf_rule_pl, rule);
+#else
 				pool_put(&pf_rule_pl, rule);
+#endif
 				error = EINVAL;
 				break;
 			}
@@ -1562,40 +1793,42 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		if (rule->rt && !rule->direction)
 			error = EINVAL;
 #if NPFLOG > 0
-#ifdef __FreeBSD__
 		if (!rule->log)
 			rule->logif = 0;
-#endif
 		if (rule->logif >= PFLOGIFS_MAX)
 			error = EINVAL;
 #endif
 		if (pf_rtlabel_add(&rule->src.addr) ||
 		    pf_rtlabel_add(&rule->dst.addr))
 			error = EBUSY;
-		if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
+		if (pf_addr_setup(ruleset, &rule->src.addr, rule->af))
 			error = EINVAL;
-		if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
-			error = EINVAL;
-		if (pf_tbladdr_setup(ruleset, &rule->src.addr))
-			error = EINVAL;
-		if (pf_tbladdr_setup(ruleset, &rule->dst.addr))
+		if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
 			error = EINVAL;
 		if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
 			error = EINVAL;
+#ifdef __FreeBSD__
+		TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
+#else
 		TAILQ_FOREACH(pa, &pf_pabuf, entries)
+#endif
 			if (pf_tbladdr_setup(ruleset, &pa->addr))
 				error = EINVAL;
 
 		if (rule->overload_tblname[0]) {
 			if ((rule->overload_tbl = pfr_attach_table(ruleset,
-			    rule->overload_tblname)) == NULL)
+			    rule->overload_tblname, 0)) == NULL)
 				error = EINVAL;
 			else
 				rule->overload_tbl->pfrkt_flags |=
 				    PFR_TFLAG_ACTIVE;
 		}
 
+#ifdef __FreeBSD__
+		pf_mv_pool(&V_pf_pabuf, &rule->rpool.list);
+#else
 		pf_mv_pool(&pf_pabuf, &rule->rpool.list);
+#endif
 		if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
 		    (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
 		    (rule->rt > PF_FASTROUTE)) &&
@@ -1608,14 +1841,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		}
 
 #ifdef __FreeBSD__
-		if (!debug_pfugidhack && (rule->uid.op || rule->gid.op ||
+		if (!V_debug_pfugidhack && (rule->uid.op || rule->gid.op ||
 		    rule->log & PF_LOG_SOCKET_LOOKUP)) {
 			DPFPRINTF(PF_DEBUG_MISC,
 			    ("pf: debug.pfugidhack enabled\n"));
-			debug_pfugidhack = 1;
+			V_debug_pfugidhack = 1;
 		}
 #endif
-
 		rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
 		rule->evaluations = rule->packets[0] = rule->packets[1] =
 		    rule->bytes[0] = rule->bytes[1] = 0;
@@ -1685,12 +1917,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			error = EBUSY;
 			break;
 		}
-		pfi_dynaddr_copyout(&pr->rule.src.addr);
-		pfi_dynaddr_copyout(&pr->rule.dst.addr);
-		pf_tbladdr_copyout(&pr->rule.src.addr);
-		pf_tbladdr_copyout(&pr->rule.dst.addr);
-		pf_rtlabel_copyout(&pr->rule.src.addr);
-		pf_rtlabel_copyout(&pr->rule.dst.addr);
+		pf_addr_copyout(&pr->rule.src.addr);
+		pf_addr_copyout(&pr->rule.dst.addr);
 		for (i = 0; i < PF_SKIP_COUNT; ++i)
 			if (rule->skip[i].ptr == NULL)
 				pr->rule.skip[i].nr = -1;
@@ -1702,6 +1930,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			rule->evaluations = 0;
 			rule->packets[0] = rule->packets[1] = 0;
 			rule->bytes[0] = rule->bytes[1] = 0;
+			rule->states_tot = 0;
 		}
 		break;
 	}
@@ -1715,7 +1944,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 
 		if (!(pcr->action == PF_CHANGE_REMOVE ||
 		    pcr->action == PF_CHANGE_GET_TICKET) &&
+#ifdef __FreeBSD__
+		    pcr->pool_ticket != V_ticket_pabuf) {
+#else
 		    pcr->pool_ticket != ticket_pabuf) {
+#endif
 			error = EBUSY;
 			break;
 		}
@@ -1752,7 +1985,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		}
 
 		if (pcr->action != PF_CHANGE_REMOVE) {
-			newrule = pool_get(&pf_rule_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+			newrule = pool_get(&V_pf_rule_pl, PR_NOWAIT);
+#else
+			newrule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL);
+#endif
 			if (newrule == NULL) {
 				error = ENOMEM;
 				break;
@@ -1767,18 +2004,26 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 #endif
 			TAILQ_INIT(&newrule->rpool.list);
 			/* initialize refcounting */
-			newrule->states = 0;
+			newrule->states_cur = 0;
 			newrule->entries.tqe_prev = NULL;
 #ifndef INET
 			if (newrule->af == AF_INET) {
+#ifdef __FreeBSD__
+				pool_put(&V_pf_rule_pl, newrule);
+#else
 				pool_put(&pf_rule_pl, newrule);
+#endif
 				error = EAFNOSUPPORT;
 				break;
 			}
 #endif /* INET */
 #ifndef INET6
 			if (newrule->af == AF_INET6) {
+#ifdef __FreeBSD__
+				pool_put(&V_pf_rule_pl, newrule);
+#else
 				pool_put(&pf_rule_pl, newrule);
+#endif
 				error = EAFNOSUPPORT;
 				break;
 			}
@@ -1786,7 +2031,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			if (newrule->ifname[0]) {
 				newrule->kif = pfi_kif_get(newrule->ifname);
 				if (newrule->kif == NULL) {
+#ifdef __FreeBSD__
+					pool_put(&V_pf_rule_pl, newrule);
+#else
 					pool_put(&pf_rule_pl, newrule);
+#endif
 					error = EINVAL;
 					break;
 				}
@@ -1826,34 +2075,32 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 					error = EBUSY;
 			if (newrule->rt && !newrule->direction)
 				error = EINVAL;
-#ifdef __FreeBSD__
 #if NPFLOG > 0
 			if (!newrule->log)
 				newrule->logif = 0;
 			if (newrule->logif >= PFLOGIFS_MAX)
 				error = EINVAL;
 #endif
-#endif
 			if (pf_rtlabel_add(&newrule->src.addr) ||
 			    pf_rtlabel_add(&newrule->dst.addr))
 				error = EBUSY;
-			if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
-				error = EINVAL;
-			if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
-				error = EINVAL;
-			if (pf_tbladdr_setup(ruleset, &newrule->src.addr))
+			if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af))
 				error = EINVAL;
-			if (pf_tbladdr_setup(ruleset, &newrule->dst.addr))
+			if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
 				error = EINVAL;
 			if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
 				error = EINVAL;
+#ifdef __FreeBSD__
+			TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
+#else
 			TAILQ_FOREACH(pa, &pf_pabuf, entries)
+#endif
 				if (pf_tbladdr_setup(ruleset, &pa->addr))
 					error = EINVAL;
 
 			if (newrule->overload_tblname[0]) {
 				if ((newrule->overload_tbl = pfr_attach_table(
-				    ruleset, newrule->overload_tblname)) ==
+				    ruleset, newrule->overload_tblname, 0)) ==
 				    NULL)
 					error = EINVAL;
 				else
@@ -1861,7 +2108,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 					    PFR_TFLAG_ACTIVE;
 			}
 
+#ifdef __FreeBSD__
+			pf_mv_pool(&V_pf_pabuf, &newrule->rpool.list);
+#else
 			pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
+#endif
 			if (((((newrule->action == PF_NAT) ||
 			    (newrule->action == PF_RDR) ||
 			    (newrule->action == PF_BINAT) ||
@@ -1876,12 +2127,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			}
 
 #ifdef __FreeBSD__
-			if (!debug_pfugidhack && (newrule->uid.op ||
+			if (!V_debug_pfugidhack && (newrule->uid.op ||
 			    newrule->gid.op ||
 			    newrule->log & PF_LOG_SOCKET_LOOKUP)) {
 				DPFPRINTF(PF_DEBUG_MISC,
 				    ("pf: debug.pfugidhack enabled\n"));
-				debug_pfugidhack = 1;
+				V_debug_pfugidhack = 1;
 			}
 #endif
 
@@ -1890,7 +2141,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			newrule->packets[0] = newrule->packets[1] = 0;
 			newrule->bytes[0] = newrule->bytes[1] = 0;
 		}
+#ifdef __FreeBSD__
+		pf_empty_pool(&V_pf_pabuf);
+#else
 		pf_empty_pool(&pf_pabuf);
+#endif
 
 		if (pcr->action == PF_CHANGE_ADD_HEAD)
 			oldrule = TAILQ_FIRST(
@@ -1943,166 +2198,164 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 	}
 
 	case DIOCCLRSTATES: {
-		struct pf_state		*state, *nexts;
+		struct pf_state		*s, *nexts;
 		struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
-		int			 killed = 0;
+		u_int			 killed = 0;
 
-		for (state = RB_MIN(pf_state_tree_id, &tree_id); state;
-		    state = nexts) {
-			nexts = RB_NEXT(pf_state_tree_id, &tree_id, state);
+#ifdef __FreeBSD__
+		for (s = RB_MIN(pf_state_tree_id, &V_tree_id); s; s = nexts) {
+			nexts = RB_NEXT(pf_state_tree_id, &V_tree_id, s);
+#else
+		for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) {
+			nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
+#endif
 
 			if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
-			    state->u.s.kif->pfik_name)) {
-#if NPFSYNC
+			    s->kif->pfik_name)) {
+#if NPFSYNC > 0
 				/* don't send out individual delete messages */
-				state->sync_flags = PFSTATE_NOSYNC;
+				SET(s->state_flags, PFSTATE_NOSYNC);
 #endif
-				pf_unlink_state(state);
+				pf_unlink_state(s);
 				killed++;
 			}
 		}
-		psk->psk_af = killed;
-#if NPFSYNC
+		psk->psk_killed = killed;
+#if NPFSYNC > 0
+#ifdef __FreeBSD__
+		if (pfsync_clear_states_ptr != NULL)
+			pfsync_clear_states_ptr(V_pf_status.hostid, psk->psk_ifname);
+#else
 		pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
 #endif
+#endif
 		break;
 	}
 
 	case DIOCKILLSTATES: {
-		struct pf_state		*state, *nexts;
-		struct pf_state_host	*src, *dst;
+		struct pf_state		*s, *nexts;
+		struct pf_state_key	*sk;
+		struct pf_addr		*srcaddr, *dstaddr;
+		u_int16_t		 srcport, dstport;
 		struct pfioc_state_kill	*psk = (struct pfioc_state_kill *)addr;
-		int			 killed = 0;
-
-		for (state = RB_MIN(pf_state_tree_id, &tree_id); state;
-		    state = nexts) {
-			nexts = RB_NEXT(pf_state_tree_id, &tree_id, state);
+		u_int			 killed = 0;
 
-			if (state->direction == PF_OUT) {
-				src = &state->lan;
-				dst = &state->ext;
+		if (psk->psk_pfcmp.id) {
+			if (psk->psk_pfcmp.creatorid == 0)
+#ifdef __FreeBSD__
+				psk->psk_pfcmp.creatorid = V_pf_status.hostid;
+#else
+				psk->psk_pfcmp.creatorid = pf_status.hostid;
+#endif
+			if ((s = pf_find_state_byid(&psk->psk_pfcmp))) {
+				pf_unlink_state(s);
+				psk->psk_killed = 1;
+			}
+			break;
+		}
+
+#ifdef __FreeBSD__
+		for (s = RB_MIN(pf_state_tree_id, &V_tree_id); s;
+		    s = nexts) {
+			nexts = RB_NEXT(pf_state_tree_id, &V_tree_id, s);
+#else
+		for (s = RB_MIN(pf_state_tree_id, &tree_id); s;
+		    s = nexts) {
+			nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
+#endif
+			sk = s->key[PF_SK_WIRE];
+
+			if (s->direction == PF_OUT) {
+				srcaddr = &sk->addr[1];
+				dstaddr = &sk->addr[0];
+				srcport = sk->port[0];
+				dstport = sk->port[0];
 			} else {
-				src = &state->ext;
-				dst = &state->lan;
+				srcaddr = &sk->addr[0];
+				dstaddr = &sk->addr[1];
+				srcport = sk->port[0];
+				dstport = sk->port[0];
 			}
-			if ((!psk->psk_af || state->af == psk->psk_af)
+			if ((!psk->psk_af || sk->af == psk->psk_af)
 			    && (!psk->psk_proto || psk->psk_proto ==
-			    state->proto) &&
+			    sk->proto) &&
 			    PF_MATCHA(psk->psk_src.neg,
 			    &psk->psk_src.addr.v.a.addr,
 			    &psk->psk_src.addr.v.a.mask,
-			    &src->addr, state->af) &&
+			    srcaddr, sk->af) &&
 			    PF_MATCHA(psk->psk_dst.neg,
 			    &psk->psk_dst.addr.v.a.addr,
 			    &psk->psk_dst.addr.v.a.mask,
-			    &dst->addr, state->af) &&
+			    dstaddr, sk->af) &&
 			    (psk->psk_src.port_op == 0 ||
 			    pf_match_port(psk->psk_src.port_op,
 			    psk->psk_src.port[0], psk->psk_src.port[1],
-			    src->port)) &&
+			    srcport)) &&
 			    (psk->psk_dst.port_op == 0 ||
 			    pf_match_port(psk->psk_dst.port_op,
 			    psk->psk_dst.port[0], psk->psk_dst.port[1],
-			    dst->port)) &&
+			    dstport)) &&
+			    (!psk->psk_label[0] || (s->rule.ptr->label[0] &&
+			    !strcmp(psk->psk_label, s->rule.ptr->label))) &&
 			    (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
-			    state->u.s.kif->pfik_name))) {
-#if NPFSYNC > 0
-				/* send immediate delete of state */
-				pfsync_delete_state(state);
-				state->sync_flags |= PFSTATE_NOSYNC;
-#endif
-				pf_unlink_state(state);
+			    s->kif->pfik_name))) {
+				pf_unlink_state(s);
 				killed++;
 			}
 		}
-		psk->psk_af = killed;
+		psk->psk_killed = killed;
 		break;
 	}
 
 	case DIOCADDSTATE: {
 		struct pfioc_state	*ps = (struct pfioc_state *)addr;
-		struct pf_state		*state;
-		struct pfi_kif		*kif;
+		struct pfsync_state	*sp = &ps->state;
 
-		if (ps->state.timeout >= PFTM_MAX &&
-		    ps->state.timeout != PFTM_UNTIL_PACKET) {
+		if (sp->timeout >= PFTM_MAX &&
+		    sp->timeout != PFTM_UNTIL_PACKET) {
 			error = EINVAL;
 			break;
 		}
-		state = pool_get(&pf_state_pl, PR_NOWAIT);
-		if (state == NULL) {
-			error = ENOMEM;
-			break;
-		}
-		kif = pfi_kif_get(ps->state.u.ifname);
-		if (kif == NULL) {
-			pool_put(&pf_state_pl, state);
-			error = ENOENT;
-			break;
-		}
-		bcopy(&ps->state, state, sizeof(struct pf_state));
-		bzero(&state->u, sizeof(state->u));
-		state->rule.ptr = &pf_default_rule;
-		state->nat_rule.ptr = NULL;
-		state->anchor.ptr = NULL;
-		state->rt_kif = NULL;
-		state->creation = time_second;
-		state->pfsync_time = 0;
-		state->packets[0] = state->packets[1] = 0;
-		state->bytes[0] = state->bytes[1] = 0;
-
-		if (pf_insert_state(kif, state)) {
-			pfi_kif_unref(kif, PFI_KIF_REF_NONE);
-			pool_put(&pf_state_pl, state);
-			error = ENOMEM;
-		}
+#ifdef __FreeBSD__
+		if (pfsync_state_import_ptr != NULL)
+			error = pfsync_state_import_ptr(sp, PFSYNC_SI_IOCTL);
+#else
+		error = pfsync_state_import(sp, PFSYNC_SI_IOCTL);
+#endif
 		break;
 	}
 
 	case DIOCGETSTATE: {
 		struct pfioc_state	*ps = (struct pfioc_state *)addr;
-		struct pf_state		*state;
-		u_int32_t		 nr;
-		int			 secs;
+		struct pf_state		*s;
+		struct pf_state_cmp	 id_key;
 
-		nr = 0;
-		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
-			if (nr >= ps->nr)
-				break;
-			nr++;
-		}
-		if (state == NULL) {
-			error = EBUSY;
+		bcopy(ps->state.id, &id_key.id, sizeof(id_key.id));
+		id_key.creatorid = ps->state.creatorid;
+
+		s = pf_find_state_byid(&id_key);
+		if (s == NULL) {
+			error = ENOENT;
 			break;
 		}
-		secs = time_second;
-		bcopy(state, &ps->state, sizeof(ps->state));
-		strlcpy(ps->state.u.ifname, state->u.s.kif->pfik_name,
-		    sizeof(ps->state.u.ifname));
-		ps->state.rule.nr = state->rule.ptr->nr;
-		ps->state.nat_rule.nr = (state->nat_rule.ptr == NULL) ?
-		    -1 : state->nat_rule.ptr->nr;
-		ps->state.anchor.nr = (state->anchor.ptr == NULL) ?
-		    -1 : state->anchor.ptr->nr;
-		ps->state.creation = secs - ps->state.creation;
-		ps->state.expire = pf_state_expires(state);
-		if (ps->state.expire > secs)
-			ps->state.expire -= secs;
-		else
-			ps->state.expire = 0;
+
+		pfsync_state_export(&ps->state, s);
 		break;
 	}
 
 	case DIOCGETSTATES: {
 		struct pfioc_states	*ps = (struct pfioc_states *)addr;
 		struct pf_state		*state;
-		struct pf_state		*p, *pstore;
+		struct pfsync_state	*p, *pstore;
 		u_int32_t		 nr = 0;
-		int			 space = ps->ps_len;
 
-		if (space == 0) {
+		if (ps->ps_len == 0) {
+#ifdef __FreeBSD__
+			nr = V_pf_status.states;
+#else
 			nr = pf_status.states;
-			ps->ps_len = sizeof(struct pf_state) * nr;
+#endif
+			ps->ps_len = sizeof(struct pfsync_state) * nr;
 			break;
 		}
 
@@ -2116,29 +2369,16 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 
 		p = ps->ps_states;
 
+#ifdef __FreeBSD__
+		state = TAILQ_FIRST(&V_state_list);
+#else
 		state = TAILQ_FIRST(&state_list);
+#endif
 		while (state) {
 			if (state->timeout != PFTM_UNLINKED) {
-				int	secs = time_second;
-
 				if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
 					break;
-
-				bcopy(state, pstore, sizeof(*pstore));
-				strlcpy(pstore->u.ifname,
-				    state->u.s.kif->pfik_name,
-				    sizeof(pstore->u.ifname));
-				pstore->rule.nr = state->rule.ptr->nr;
-				pstore->nat_rule.nr = (state->nat_rule.ptr ==
-				    NULL) ? -1 : state->nat_rule.ptr->nr;
-				pstore->anchor.nr = (state->anchor.ptr ==
-				    NULL) ? -1 : state->anchor.ptr->nr;
-				pstore->creation = secs - pstore->creation;
-				pstore->expire = pf_state_expires(state);
-				if (pstore->expire > secs)
-					pstore->expire -= secs;
-				else
-					pstore->expire = 0;
+				pfsync_state_export(pstore, state);
 #ifdef __FreeBSD__
 				PF_COPYOUT(pstore, p, sizeof(*p), error);
 #else
@@ -2151,10 +2391,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 				p++;
 				nr++;
 			}
-			state = TAILQ_NEXT(state, u.s.entry_list);
+			state = TAILQ_NEXT(state, entry_list);
 		}
 
-		ps->ps_len = sizeof(struct pf_state) * nr;
+		ps->ps_len = sizeof(struct pfsync_state) * nr;
 
 		free(pstore, M_TEMP);
 		break;
@@ -2162,8 +2402,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 
 	case DIOCGETSTATUS: {
 		struct pf_status *s = (struct pf_status *)addr;
+#ifdef __FreeBSD__
+		bcopy(&V_pf_status, s, sizeof(struct pf_status));
+#else
 		bcopy(&pf_status, s, sizeof(struct pf_status));
-		pfi_fill_oldstatus(s);
+#endif
+		pfi_update_status(s->ifname, s);
 		break;
 	}
 
@@ -2171,35 +2415,51 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		struct pfioc_if	*pi = (struct pfioc_if *)addr;
 
 		if (pi->ifname[0] == 0) {
+#ifdef __FreeBSD__
+			bzero(V_pf_status.ifname, IFNAMSIZ);
+#else
 			bzero(pf_status.ifname, IFNAMSIZ);
+#endif
 			break;
 		}
-		if (ifunit(pi->ifname) == NULL) {
-			error = EINVAL;
-			break;
-		}
+#ifdef __FreeBSD__
+		strlcpy(V_pf_status.ifname, pi->ifname, IFNAMSIZ);
+#else
 		strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
+#endif
 		break;
 	}
 
 	case DIOCCLRSTATUS: {
+#ifdef __FreeBSD__
+		bzero(V_pf_status.counters, sizeof(V_pf_status.counters));
+		bzero(V_pf_status.fcounters, sizeof(V_pf_status.fcounters));
+		bzero(V_pf_status.scounters, sizeof(V_pf_status.scounters));
+		V_pf_status.since = time_second;
+		if (*V_pf_status.ifname)
+			pfi_update_status(V_pf_status.ifname, NULL);
+#else
 		bzero(pf_status.counters, sizeof(pf_status.counters));
 		bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
 		bzero(pf_status.scounters, sizeof(pf_status.scounters));
 		pf_status.since = time_second;
 		if (*pf_status.ifname)
-			pfi_clr_istats(pf_status.ifname);
+			pfi_update_status(pf_status.ifname, NULL);
+#endif
 		break;
 	}
 
 	case DIOCNATLOOK: {
 		struct pfioc_natlook	*pnl = (struct pfioc_natlook *)addr;
+		struct pf_state_key	*sk;
 		struct pf_state		*state;
-		struct pf_state_cmp	 key;
+		struct pf_state_key_cmp	 key;
 		int			 m = 0, direction = pnl->direction;
+		int			 sidx, didx;
 
-		key.af = pnl->af;
-		key.proto = pnl->proto;
+		/* NATLOOK src and dst are reversed, so reverse sidx/didx */
+		sidx = (direction == PF_IN) ? 1 : 0;
+		didx = (direction == PF_IN) ? 0 : 1;
 
 		if (!pnl->proto ||
 		    PF_AZERO(&pnl->saddr, pnl->af) ||
@@ -2209,43 +2469,23 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		    (!pnl->dport || !pnl->sport)))
 			error = EINVAL;
 		else {
-			/*
-			 * userland gives us source and dest of connection,
-			 * reverse the lookup so we ask for what happens with
-			 * the return traffic, enabling us to find it in the
-			 * state tree.
-			 */
-			if (direction == PF_IN) {
-				PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
-				key.ext.port = pnl->dport;
-				PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
-				key.gwy.port = pnl->sport;
-				state = pf_find_state_all(&key, PF_EXT_GWY, &m);
-			} else {
-				PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
-				key.lan.port = pnl->dport;
-				PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
-				key.ext.port = pnl->sport;
-				state = pf_find_state_all(&key, PF_LAN_EXT, &m);
-			}
+			key.af = pnl->af;
+			key.proto = pnl->proto;
+			PF_ACPY(&key.addr[sidx], &pnl->saddr, pnl->af);
+			key.port[sidx] = pnl->sport;
+			PF_ACPY(&key.addr[didx], &pnl->daddr, pnl->af);
+			key.port[didx] = pnl->dport;
+
+			state = pf_find_state_all(&key, direction, &m);
+
 			if (m > 1)
 				error = E2BIG;	/* more than one state */
 			else if (state != NULL) {
-				if (direction == PF_IN) {
-					PF_ACPY(&pnl->rsaddr, &state->lan.addr,
-					    state->af);
-					pnl->rsport = state->lan.port;
-					PF_ACPY(&pnl->rdaddr, &pnl->daddr,
-					    pnl->af);
-					pnl->rdport = pnl->dport;
-				} else {
-					PF_ACPY(&pnl->rdaddr, &state->gwy.addr,
-					    state->af);
-					pnl->rdport = state->gwy.port;
-					PF_ACPY(&pnl->rsaddr, &pnl->saddr,
-					    pnl->af);
-					pnl->rsport = pnl->sport;
-				}
+				sk = state->key[sidx];
+				PF_ACPY(&pnl->rsaddr, &sk->addr[sidx], sk->af);
+				pnl->rsport = sk->port[sidx];
+				PF_ACPY(&pnl->rdaddr, &sk->addr[didx], sk->af);
+				pnl->rdport = sk->port[didx];
 			} else
 				error = ENOENT;
 		}
@@ -2261,10 +2501,18 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			error = EINVAL;
 			goto fail;
 		}
+#ifdef __FreeBSD__
+		old = V_pf_default_rule.timeout[pt->timeout];
+#else
 		old = pf_default_rule.timeout[pt->timeout];
+#endif
 		if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
 			pt->seconds = 1;
+#ifdef __FreeBSD__
+		V_pf_default_rule.timeout[pt->timeout] = pt->seconds;
+#else
 		pf_default_rule.timeout[pt->timeout] = pt->seconds;
+#endif
 		if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
 			wakeup(pf_purge_thread);
 		pt->seconds = old;
@@ -2278,7 +2526,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			error = EINVAL;
 			goto fail;
 		}
+#ifdef __FreeBSD__
+		pt->seconds = V_pf_default_rule.timeout[pt->timeout];
+#else
 		pt->seconds = pf_default_rule.timeout[pt->timeout];
+#endif
 		break;
 	}
 
@@ -2289,7 +2541,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			error = EINVAL;
 			goto fail;
 		}
+#ifdef __FreeBSD__
+		pl->limit = V_pf_pool_limits[pl->index].limit;
+#else
 		pl->limit = pf_pool_limits[pl->index].limit;
+#endif
 		break;
 	}
 
@@ -2298,29 +2554,40 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		int			 old_limit;
 
 		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
+#ifdef __FreeBSD__
+		    V_pf_pool_limits[pl->index].pp == NULL) {
+#else
 		    pf_pool_limits[pl->index].pp == NULL) {
+#endif
 			error = EINVAL;
 			goto fail;
 		}
 #ifdef __FreeBSD__
-		uma_zone_set_max(pf_pool_limits[pl->index].pp, pl->limit);
+		uma_zone_set_max(V_pf_pool_limits[pl->index].pp, pl->limit);
+		old_limit = V_pf_pool_limits[pl->index].limit;
+		V_pf_pool_limits[pl->index].limit = pl->limit;
+		pl->limit = old_limit;
 #else
 		if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
 		    pl->limit, NULL, 0) != 0) {
 			error = EBUSY;
 			goto fail;
 		}
-#endif
 		old_limit = pf_pool_limits[pl->index].limit;
 		pf_pool_limits[pl->index].limit = pl->limit;
 		pl->limit = old_limit;
+#endif
 		break;
 	}
 
 	case DIOCSETDEBUG: {
 		u_int32_t	*level = (u_int32_t *)addr;
 
+#ifdef __FreeBSD__
+		V_pf_status.debug = *level;
+#else
 		pf_status.debug = *level;
+#endif
 		break;
 	}
 
@@ -2363,11 +2630,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		struct pf_altq		*altq;
 
 		/* enable all altq interfaces on active list */
-		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
 #ifdef __FreeBSD__
+		TAILQ_FOREACH(altq, V_pf_altqs_active, entries) {
 			if (altq->qname[0] == 0 && (altq->local_flags &
 			    PFALTQ_FLAG_IF_REMOVED) == 0) {
 #else
+		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
 			if (altq->qname[0] == 0) {
 #endif
 				error = pf_enable_altq(altq);
@@ -2376,7 +2644,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			}
 		}
 		if (error == 0)
+#ifdef __FreeBSD__
+			V_pf_altq_running = 1;
+#else
 			pf_altq_running = 1;
+#endif
 		DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
 		break;
 	}
@@ -2385,11 +2657,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		struct pf_altq		*altq;
 
 		/* disable all altq interfaces on active list */
-		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
 #ifdef __FreeBSD__
+		TAILQ_FOREACH(altq, V_pf_altqs_active, entries) {
 			if (altq->qname[0] == 0 && (altq->local_flags &
 			    PFALTQ_FLAG_IF_REMOVED) == 0) {
 #else
+		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
 			if (altq->qname[0] == 0) {
 #endif
 				error = pf_disable_altq(altq);
@@ -2398,7 +2671,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			}
 		}
 		if (error == 0)
+#ifdef __FreeBSD__
+			V_pf_altq_running = 0;
+#else
 			pf_altq_running = 0;
+#endif
 		DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
 		break;
 	}
@@ -2407,11 +2684,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		struct pfioc_altq	*pa = (struct pfioc_altq *)addr;
 		struct pf_altq		*altq, *a;
 
+#ifdef __FreeBSD__
+		if (pa->ticket != V_ticket_altqs_inactive) {
+#else
 		if (pa->ticket != ticket_altqs_inactive) {
+#endif
 			error = EBUSY;
 			break;
 		}
-		altq = pool_get(&pf_altq_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+		altq = pool_get(&V_pf_altq_pl, PR_NOWAIT);
+#else
+		altq = pool_get(&pf_altq_pl, PR_WAITOK|PR_LIMITFAIL);
+#endif
 		if (altq == NULL) {
 			error = ENOMEM;
 			break;
@@ -2428,11 +2713,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		if (altq->qname[0] != 0) {
 			if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
 				error = EBUSY;
+#ifdef __FreeBSD__
+				pool_put(&V_pf_altq_pl, altq);
+#else
 				pool_put(&pf_altq_pl, altq);
+#endif
 				break;
 			}
 			altq->altq_disc = NULL;
+#ifdef __FreeBSD__
+			TAILQ_FOREACH(a, V_pf_altqs_inactive, entries) {
+#else
 			TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
+#endif
 				if (strncmp(a->ifname, altq->ifname,
 				    IFNAMSIZ) == 0 && a->qname[0] == 0) {
 					altq->altq_disc = a->altq_disc;
@@ -2448,18 +2741,26 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
 		} else {
 			PF_UNLOCK();
-#endif		
+#endif
 		error = altq_add(altq);
 #ifdef __FreeBSD__
 			PF_LOCK();
 		}
 #endif
 		if (error) {
+#ifdef __FreeBSD__
+			pool_put(&V_pf_altq_pl, altq);
+#else
 			pool_put(&pf_altq_pl, altq);
+#endif
 			break;
 		}
 
+#ifdef __FreeBSD__
+		TAILQ_INSERT_TAIL(V_pf_altqs_inactive, altq, entries);
+#else
 		TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
+#endif
 		bcopy(altq, &pa->altq, sizeof(struct pf_altq));
 		break;
 	}
@@ -2469,9 +2770,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		struct pf_altq		*altq;
 
 		pa->nr = 0;
+#ifdef __FreeBSD__
+		TAILQ_FOREACH(altq, V_pf_altqs_active, entries)
+			pa->nr++;
+		pa->ticket = V_ticket_altqs_active;
+#else
 		TAILQ_FOREACH(altq, pf_altqs_active, entries)
 			pa->nr++;
 		pa->ticket = ticket_altqs_active;
+#endif
 		break;
 	}
 
@@ -2480,12 +2787,20 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		struct pf_altq		*altq;
 		u_int32_t		 nr;
 
+#ifdef __FreeBSD__
+		if (pa->ticket != V_ticket_altqs_active) {
+#else
 		if (pa->ticket != ticket_altqs_active) {
+#endif
 			error = EBUSY;
 			break;
 		}
 		nr = 0;
+#ifdef __FreeBSD__
+		altq = TAILQ_FIRST(V_pf_altqs_active);
+#else
 		altq = TAILQ_FIRST(pf_altqs_active);
+#endif
 		while ((altq != NULL) && (nr < pa->nr)) {
 			altq = TAILQ_NEXT(altq, entries);
 			nr++;
@@ -2509,13 +2824,21 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		u_int32_t		 nr;
 		int			 nbytes;
 
+#ifdef __FreeBSD__
+		if (pq->ticket != V_ticket_altqs_active) {
+#else
 		if (pq->ticket != ticket_altqs_active) {
+#endif
 			error = EBUSY;
 			break;
 		}
 		nbytes = pq->nbytes;
 		nr = 0;
+#ifdef __FreeBSD__
+		altq = TAILQ_FIRST(V_pf_altqs_active);
+#else
 		altq = TAILQ_FIRST(pf_altqs_active);
+#endif
 		while ((altq != NULL) && (nr < pq->nr)) {
 			altq = TAILQ_NEXT(altq, entries);
 			nr++;
@@ -2524,6 +2847,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			error = EBUSY;
 			break;
 		}
+
 #ifdef __FreeBSD__
 		if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
 			error = ENXIO;
@@ -2546,15 +2870,24 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 	case DIOCBEGINADDRS: {
 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
 
+#ifdef __FreeBSD__
+		pf_empty_pool(&V_pf_pabuf);
+		pp->ticket = ++V_ticket_pabuf;
+#else
 		pf_empty_pool(&pf_pabuf);
 		pp->ticket = ++ticket_pabuf;
+#endif
 		break;
 	}
 
 	case DIOCADDADDR: {
 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
 
+#ifdef __FreeBSD__
+		if (pp->ticket != V_ticket_pabuf) {
+#else
 		if (pp->ticket != ticket_pabuf) {
+#endif
 			error = EBUSY;
 			break;
 		}
@@ -2576,7 +2909,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			error = EINVAL;
 			break;
 		}
-		pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+		pa = pool_get(&V_pf_pooladdr_pl, PR_NOWAIT);
+#else
+		pa = pool_get(&pf_pooladdr_pl, PR_WAITOK|PR_LIMITFAIL);
+#endif
 		if (pa == NULL) {
 			error = ENOMEM;
 			break;
@@ -2585,7 +2922,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		if (pa->ifname[0]) {
 			pa->kif = pfi_kif_get(pa->ifname);
 			if (pa->kif == NULL) {
+#ifdef __FreeBSD__
+				pool_put(&V_pf_pooladdr_pl, pa);
+#else
 				pool_put(&pf_pooladdr_pl, pa);
+#endif
 				error = EINVAL;
 				break;
 			}
@@ -2594,11 +2935,19 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
 			pfi_dynaddr_remove(&pa->addr);
 			pfi_kif_unref(pa->kif, PFI_KIF_REF_RULE);
+#ifdef __FreeBSD__
+			pool_put(&V_pf_pooladdr_pl, pa);
+#else
 			pool_put(&pf_pooladdr_pl, pa);
+#endif
 			error = EINVAL;
 			break;
 		}
+#ifdef __FreeBSD__
+		TAILQ_INSERT_TAIL(&V_pf_pabuf, pa, entries);
+#else
 		TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
+#endif
 		break;
 	}
 
@@ -2637,9 +2986,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			break;
 		}
 		bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
-		pfi_dynaddr_copyout(&pp->addr.addr);
-		pf_tbladdr_copyout(&pp->addr.addr);
-		pf_rtlabel_copyout(&pp->addr.addr);
+		pf_addr_copyout(&pp->addr.addr);
 		break;
 	}
 
@@ -2672,7 +3019,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			break;
 		}
 		if (pca->action != PF_CHANGE_REMOVE) {
-			newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+			newpa = pool_get(&V_pf_pooladdr_pl,
+			    PR_NOWAIT);
+#else
+			newpa = pool_get(&pf_pooladdr_pl,
+			    PR_WAITOK|PR_LIMITFAIL);
+#endif
 			if (newpa == NULL) {
 				error = ENOMEM;
 				break;
@@ -2680,14 +3033,22 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
 #ifndef INET
 			if (pca->af == AF_INET) {
+#ifdef __FreeBSD__
+				pool_put(&V_pf_pooladdr_pl, newpa);
+#else
 				pool_put(&pf_pooladdr_pl, newpa);
+#endif
 				error = EAFNOSUPPORT;
 				break;
 			}
 #endif /* INET */
 #ifndef INET6
 			if (pca->af == AF_INET6) {
+#ifdef __FreeBSD__
+				pool_put(&V_pf_pooladdr_pl, newpa);
+#else
 				pool_put(&pf_pooladdr_pl, newpa);
+#endif
 				error = EAFNOSUPPORT;
 				break;
 			}
@@ -2695,7 +3056,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			if (newpa->ifname[0]) {
 				newpa->kif = pfi_kif_get(newpa->ifname);
 				if (newpa->kif == NULL) {
+#ifdef __FreeBSD__
+					pool_put(&V_pf_pooladdr_pl, newpa);
+#else
 					pool_put(&pf_pooladdr_pl, newpa);
+#endif
 					error = EINVAL;
 					break;
 				}
@@ -2706,7 +3071,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			    pf_tbladdr_setup(ruleset, &newpa->addr)) {
 				pfi_dynaddr_remove(&newpa->addr);
 				pfi_kif_unref(newpa->kif, PFI_KIF_REF_RULE);
+#ifdef __FreeBSD__
+				pool_put(&V_pf_pooladdr_pl, newpa);
+#else
 				pool_put(&pf_pooladdr_pl, newpa);
+#endif
 				error = EINVAL;
 				break;
 			}
@@ -2735,7 +3104,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			pfi_dynaddr_remove(&oldpa->addr);
 			pf_tbladdr_remove(&oldpa->addr);
 			pfi_kif_unref(oldpa->kif, PFI_KIF_REF_RULE);
+#ifdef __FreeBSD__
+			pool_put(&V_pf_pooladdr_pl, oldpa);
+#else
 			pool_put(&pf_pooladdr_pl, oldpa);
+#endif
 		} else {
 			if (oldpa == NULL)
 				TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
@@ -2766,7 +3139,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		pr->nr = 0;
 		if (ruleset->anchor == NULL) {
 			/* XXX kludge for pf_main_ruleset */
+#ifdef __FreeBSD__
+			RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors)
+#else
 			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
+#endif
 				if (anchor->parent == NULL)
 					pr->nr++;
 		} else {
@@ -2791,7 +3168,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		pr->name[0] = 0;
 		if (ruleset->anchor == NULL) {
 			/* XXX kludge for pf_main_ruleset */
+#ifdef __FreeBSD__
+			RB_FOREACH(anchor, pf_anchor_global, &V_pf_anchors)
+#else
 			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
+#endif
 				if (anchor->parent == NULL && nr++ == pr->nr) {
 					strlcpy(pr->name, anchor->name,
 					    sizeof(pr->name));
@@ -3036,17 +3417,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 #ifdef __FreeBSD__
 		PF_UNLOCK();
 #endif
-		ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
-		    M_TEMP, M_WAITOK);
-		table = (struct pfr_table *)malloc(sizeof(*table),
-		    M_TEMP, M_WAITOK);
+		ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
+		table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
 #ifdef __FreeBSD__
 		PF_LOCK();
 #endif
 		for (i = 0; i < io->size; i++) {
 #ifdef __FreeBSD__
-			PF_COPYIN(io->array+i, ioe, sizeof(*ioe), error);
-			if (error) {
+		PF_COPYIN(io->array+i, ioe, sizeof(*ioe), error);
+		if (error) {
 #else
 			if (copyin(io->array+i, ioe, sizeof(*ioe))) {
 #endif
@@ -3122,10 +3501,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 #ifdef __FreeBSD__
 		PF_UNLOCK();
 #endif
-		ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
-		    M_TEMP, M_WAITOK);
-		table = (struct pfr_table *)malloc(sizeof(*table),
-		    M_TEMP, M_WAITOK);
+		ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
+		table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
 #ifdef __FreeBSD__
 		PF_LOCK();
 #endif
@@ -3197,10 +3574,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 #ifdef __FreeBSD__
 		PF_UNLOCK();
 #endif
-		ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
-		    M_TEMP, M_WAITOK);
-		table = (struct pfr_table *)malloc(sizeof(*table),
-		    M_TEMP, M_WAITOK);
+		ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
+		table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
 #ifdef __FreeBSD__
 		PF_LOCK();
 #endif
@@ -3226,8 +3601,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 					error = EINVAL;
 					goto fail;
 				}
+#ifdef __FreeBSD__
+				if (!V_altqs_inactive_open || ioe->ticket !=
+				    V_ticket_altqs_inactive) {
+#else
 				if (!altqs_inactive_open || ioe->ticket !=
 				    ticket_altqs_inactive) {
+#endif
 					free(table, M_TEMP);
 					free(ioe, M_TEMP);
 					error = EBUSY;
@@ -3238,7 +3618,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 			case PF_RULESET_TABLE:
 				rs = pf_find_ruleset(ioe->anchor);
 				if (rs == NULL || !rs->topen || ioe->ticket !=
-				     rs->tticket) {
+				    rs->tticket) {
 					free(table, M_TEMP);
 					free(ioe, M_TEMP);
 					error = EBUSY;
@@ -3322,7 +3702,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		int			 space = psn->psn_len;
 
 		if (space == 0) {
+#ifdef __FreeBSD__
+			RB_FOREACH(n, pf_src_tree, &V_tree_src_tracking)
+#else
 			RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
+#endif
 				nr++;
 			psn->psn_len = sizeof(struct pf_src_node) * nr;
 			break;
@@ -3335,9 +3719,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 #ifdef __FreeBSD__
 		PF_LOCK();
 #endif
-
 		p = psn->psn_src_nodes;
+#ifdef __FreeBSD__
+		RB_FOREACH(n, pf_src_tree, &V_tree_src_tracking) {
+#else
 		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
+#endif
 			int	secs = time_second, diff;
 
 			if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
@@ -3383,39 +3770,59 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		struct pf_src_node	*n;
 		struct pf_state		*state;
 
+#ifdef __FreeBSD__
+		RB_FOREACH(state, pf_state_tree_id, &V_tree_id) {
+#else
 		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+#endif
 			state->src_node = NULL;
 			state->nat_src_node = NULL;
 		}
+#ifdef __FreeBSD__
+		RB_FOREACH(n, pf_src_tree, &V_tree_src_tracking) {
+#else
 		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
+#endif
 			n->expire = 1;
 			n->states = 0;
 		}
 		pf_purge_expired_src_nodes(1);
+#ifdef __FreeBSD__
+		V_pf_status.src_nodes = 0;
+#else
 		pf_status.src_nodes = 0;
+#endif
 		break;
 	}
 
 	case DIOCKILLSRCNODES: {
 		struct pf_src_node	*sn;
 		struct pf_state		*s;
-		struct pfioc_src_node_kill *psnk = \
-			(struct pfioc_src_node_kill *) addr;
-		int			killed = 0;
+		struct pfioc_src_node_kill *psnk =
+		    (struct pfioc_src_node_kill *)addr;
+		u_int			killed = 0;
 
+#ifdef __FreeBSD__
+		RB_FOREACH(sn, pf_src_tree, &V_tree_src_tracking) {
+#else
 		RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
-        		if (PF_MATCHA(psnk->psnk_src.neg, \
-				      &psnk->psnk_src.addr.v.a.addr, \
-				      &psnk->psnk_src.addr.v.a.mask, \
-				      &sn->addr, sn->af) &&
-			    PF_MATCHA(psnk->psnk_dst.neg, \
-				      &psnk->psnk_dst.addr.v.a.addr, \
-				      &psnk->psnk_dst.addr.v.a.mask, \
-				      &sn->raddr, sn->af)) {
+#endif
+			if (PF_MATCHA(psnk->psnk_src.neg,
+				&psnk->psnk_src.addr.v.a.addr,
+				&psnk->psnk_src.addr.v.a.mask,
+				&sn->addr, sn->af) &&
+			    PF_MATCHA(psnk->psnk_dst.neg,
+				&psnk->psnk_dst.addr.v.a.addr,
+				&psnk->psnk_dst.addr.v.a.mask,
+				&sn->raddr, sn->af)) {
 				/* Handle state to src_node linkage */
 				if (sn->states != 0) {
-					RB_FOREACH(s, pf_state_tree_id, 
+					RB_FOREACH(s, pf_state_tree_id,
+#ifdef __FreeBSD__
+					    &V_tree_id) {
+#else
 					    &tree_id) {
+#endif
 						if (s->src_node == sn)
 							s->src_node = NULL;
 						if (s->nat_src_node == sn)
@@ -3431,17 +3838,24 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
 		if (killed > 0)
 			pf_purge_expired_src_nodes(1);
 
-		psnk->psnk_af = killed;
+		psnk->psnk_killed = killed;
 		break;
 	}
 
 	case DIOCSETHOSTID: {
 		u_int32_t	*hostid = (u_int32_t *)addr;
 
+#ifdef __FreeBSD__
+		if (*hostid == 0)
+			V_pf_status.hostid = arc4random();
+		else
+			V_pf_status.hostid = *hostid;
+#else
 		if (*hostid == 0)
 			pf_status.hostid = arc4random();
 		else
 			pf_status.hostid = *hostid;
+#endif
 		break;
 	}
 
@@ -3484,43 +3898,110 @@ fail:
 	PF_UNLOCK();
 
 	if (flags & FWRITE)
-		sx_xunlock(&pf_consistency_lock);
+		sx_xunlock(&V_pf_consistency_lock);
 	else
-		sx_sunlock(&pf_consistency_lock);
+		sx_sunlock(&V_pf_consistency_lock);
 #else
 	splx(s);
-	/* XXX: Lock order? */
 	if (flags & FWRITE)
 		rw_exit_write(&pf_consistency_lock);
 	else
 		rw_exit_read(&pf_consistency_lock);
 #endif
+
+	CURVNET_RESTORE();
+
 	return (error);
 }
 
 #ifdef __FreeBSD__
+void
+pfsync_state_export(struct pfsync_state *sp, struct pf_state *st)
+{
+	bzero(sp, sizeof(struct pfsync_state));
+
+	/* copy from state key */
+	sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0];
+	sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1];
+	sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0];
+	sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1];
+	sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0];
+	sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1];
+	sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0];
+	sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1];
+	sp->proto = st->key[PF_SK_WIRE]->proto;
+	sp->af = st->key[PF_SK_WIRE]->af;
+
+	/* copy from state */
+	strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname));
+	bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
+	sp->creation = htonl(time_second - st->creation);
+	sp->expire = pf_state_expires(st);
+	if (sp->expire <= time_second)
+		sp->expire = htonl(0);
+	else
+		sp->expire = htonl(sp->expire - time_second);
+
+	sp->direction = st->direction;
+	sp->log = st->log;
+	sp->timeout = st->timeout;
+	sp->state_flags = st->state_flags;
+	if (st->src_node)
+		sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
+	if (st->nat_src_node)
+		sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
+
+	bcopy(&st->id, &sp->id, sizeof(sp->id));
+	sp->creatorid = st->creatorid;
+	pf_state_peer_hton(&st->src, &sp->src);
+	pf_state_peer_hton(&st->dst, &sp->dst);
+
+	if (st->rule.ptr == NULL)
+		sp->rule = htonl(-1);
+	else
+		sp->rule = htonl(st->rule.ptr->nr);
+	if (st->anchor.ptr == NULL)
+		sp->anchor = htonl(-1);
+	else
+		sp->anchor = htonl(st->anchor.ptr->nr);
+	if (st->nat_rule.ptr == NULL)
+		sp->nat_rule = htonl(-1);
+	else
+		sp->nat_rule = htonl(st->nat_rule.ptr->nr);
+
+	pf_state_counter_hton(st->packets[0], sp->packets[0]);
+	pf_state_counter_hton(st->packets[1], sp->packets[1]);
+	pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
+	pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
+
+}
+
 /*
  * XXX - Check for version missmatch!!!
  */
 static void
 pf_clear_states(void)
 {
-	struct pf_state		*state;
-
+	struct pf_state	*state;
+ 
+#ifdef __FreeBSD__
+	RB_FOREACH(state, pf_state_tree_id, &V_tree_id) {
+#else
 	RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+#endif
 		state->timeout = PFTM_PURGE;
 #if NPFSYNC
 		/* don't send out individual delete messages */
-		state->sync_flags = PFSTATE_NOSYNC;
+		state->sync_state = PFSTATE_NOSYNC;
 #endif
 		pf_unlink_state(state);
 	}
-
+ 
 #if 0 /* NPFSYNC */
 /*
  * XXX This is called on module unload, we do not want to sync that over? */
  */
-	pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
+	pfsync_clear_states(V_pf_status.hostid, psk->psk_ifname);
 #endif
 }
 
@@ -3544,11 +4025,19 @@ pf_clear_srcnodes(void)
 	struct pf_src_node	*n;
 	struct pf_state		*state;
 
+#ifdef __FreeBSD__
+	RB_FOREACH(state, pf_state_tree_id, &V_tree_id) {
+#else
 	RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+#endif
 		state->src_node = NULL;
 		state->nat_src_node = NULL;
 	}
+#ifdef __FreeBSD__
+	RB_FOREACH(n, pf_src_tree, &V_tree_src_tracking) {
+#else
 	RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
+#endif
 		n->expire = 1;
 		n->states = 0;
 	}
@@ -3566,8 +4055,8 @@ shutdown_pf(void)
 	int error = 0;
 	u_int32_t t[5];
 	char nn = '\0';
-
-	pf_status.running = 0;
+ 
+	V_pf_status.running = 0;
 	do {
 		if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
 		    != 0) {
@@ -3577,22 +4066,22 @@ shutdown_pf(void)
 		if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn))
 		    != 0) {
 			DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: FILTER\n"));
-			break;		/* XXX: rollback? */
+			break;          /* XXX: rollback? */
 		}
 		if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn))
 		    != 0) {
 			DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: NAT\n"));
-			break;		/* XXX: rollback? */
+			break;          /* XXX: rollback? */
 		}
 		if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn))
 		    != 0) {
 			DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: BINAT\n"));
-			break;		/* XXX: rollback? */
+			break;          /* XXX: rollback? */
 		}
 		if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn))
 		    != 0) {
 			DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: RDR\n"));
-			break;		/* XXX: rollback? */
+			break;          /* XXX: rollback? */
 		}
 
 		/* XXX: these should always succeed here */
@@ -3605,13 +4094,13 @@ shutdown_pf(void)
 		if ((error = pf_clear_tables()) != 0)
 			break;
 
-#ifdef ALTQ
+	#ifdef ALTQ
 		if ((error = pf_begin_altq(&t[0])) != 0) {
 			DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: ALTQ\n"));
 			break;
 		}
 		pf_commit_altq(t[0]);
-#endif
+	#endif
 
 		pf_clear_states();
 
@@ -3621,7 +4110,7 @@ shutdown_pf(void)
 		/* fingerprints and interfaces have thier own cleanup code */
 	} while(0);
 
-        return (error);
+	return (error);
 }
 
 #ifdef INET
@@ -3643,10 +4132,12 @@ pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
 	if ((*m)->m_pkthdr.len >= (int)sizeof(struct ip)) {
 		/* if m_pkthdr.len is less than ip header, pf will handle. */
 		h = mtod(*m, struct ip *);
-	        HTONS(h->ip_len);
-	        HTONS(h->ip_off);
+		HTONS(h->ip_len);
+		HTONS(h->ip_off);
 	}
+	CURVNET_SET(ifp->if_vnet);
 	chk = pf_test(PF_IN, ifp, m, NULL, inp);
+	CURVNET_RESTORE();
 	if (chk && *m) {
 		m_freem(*m);
 		*m = NULL;
@@ -3683,10 +4174,12 @@ pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
 	if ((*m)->m_pkthdr.len >= (int)sizeof(*h)) {
 		/* if m_pkthdr.len is less than ip header, pf will handle. */
 		h = mtod(*m, struct ip *);
-	        HTONS(h->ip_len);
-	        HTONS(h->ip_off);
+		HTONS(h->ip_len);
+		HTONS(h->ip_off);
 	}
+	CURVNET_SET(ifp->if_vnet);
 	chk = pf_test(PF_OUT, ifp, m, NULL, inp);
+	CURVNET_RESTORE();
 	if (chk && *m) {
 		m_freem(*m);
 		*m = NULL;
@@ -3717,8 +4210,10 @@ pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
 	 * order to support scoped addresses. In order to support stateful
 	 * filtering we have change this to lo0 as it is the case in IPv4.
 	 */
+	CURVNET_SET(ifp->if_vnet);
 	chk = pf_test6(PF_IN, (*m)->m_flags & M_LOOP ? V_loif : ifp, m,
 	    NULL, inp);
+	CURVNET_RESTORE();
 	if (chk && *m) {
 		m_freem(*m);
 		*m = NULL;
@@ -3743,7 +4238,9 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
 #endif
 		(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
 	}
+	CURVNET_SET(ifp->if_vnet);
 	chk = pf_test6(PF_OUT, ifp, m, NULL, inp);
+	CURVNET_RESTORE();
 	if (chk && *m) {
 		m_freem(*m);
 		*m = NULL;
@@ -3755,20 +4252,22 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
 static int
 hook_pf(void)
 {
+#ifdef INET
 	struct pfil_head *pfh_inet;
+#endif
 #ifdef INET6
 	struct pfil_head *pfh_inet6;
 #endif
-	
+
 	PF_ASSERT(MA_NOTOWNED);
 
-	if (pf_pfil_hooked)
+	if (V_pf_pfil_hooked)
 		return (0); 
-	
+
+#ifdef INET
 	pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
 	if (pfh_inet == NULL)
 		return (ESRCH); /* XXX */
-#ifdef INET
 	pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
 	pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
 #endif
@@ -3787,27 +4286,29 @@ hook_pf(void)
 	pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
 #endif
 
-	pf_pfil_hooked = 1;
+	V_pf_pfil_hooked = 1;
 	return (0);
 }
 
 static int
 dehook_pf(void)
 {
+#ifdef INET
 	struct pfil_head *pfh_inet;
+#endif
 #ifdef INET6
 	struct pfil_head *pfh_inet6;
 #endif
 
 	PF_ASSERT(MA_NOTOWNED);
 
-	if (pf_pfil_hooked == 0)
+	if (V_pf_pfil_hooked == 0)
 		return (0);
 
+#ifdef INET
 	pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
 	if (pfh_inet == NULL)
 		return (ESRCH); /* XXX */
-#ifdef INET
 	pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
 	    pfh_inet);
 	pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
@@ -3823,21 +4324,69 @@ dehook_pf(void)
 	    pfh_inet6);
 #endif
 
-	pf_pfil_hooked = 0;
+	V_pf_pfil_hooked = 0;
+	return (0);
+}
+
+/* Vnet accessors */
+static int
+vnet_pf_init(const void *unused) 
+{
+
+	V_pf_pfil_hooked = 0;
+	V_pf_end_threads = 0;
+
+	V_debug_pfugidhack = 0;
+
+	TAILQ_INIT(&V_pf_tags);
+	TAILQ_INIT(&V_pf_qids);
+
+	pf_load();
+
 	return (0);
 }
 
 static int
+vnet_pf_uninit(const void *unused)
+{
+
+	pf_unload();
+
+	return (0);
+}
+
+/* Define startup order. */
+#define	PF_SYSINIT_ORDER	SI_SUB_PROTO_BEGIN
+#define	PF_MODEVENT_ORDER	(SI_ORDER_FIRST) /* On boot slot in here. */
+#define	PF_VNET_ORDER		(PF_MODEVENT_ORDER + 2) /* Later still. */
+
+/*
+ * Starting up.
+ * VNET_SYSINIT is called for each existing vnet and each new vnet.
+ */
+VNET_SYSINIT(vnet_pf_init, PF_SYSINIT_ORDER, PF_VNET_ORDER,
+    vnet_pf_init, NULL);
+
+/*
+ * Closing up shop. These are done in REVERSE ORDER,
+ * Not called on reboot.
+ * VNET_SYSUNINIT is called for each exiting vnet as it exits.
+ */
+VNET_SYSUNINIT(vnet_pf_uninit, PF_SYSINIT_ORDER, PF_VNET_ORDER,
+    vnet_pf_uninit, NULL);
+
+static int
 pf_load(void)
 {
+
 	init_zone_var();
+	sx_init(&V_pf_consistency_lock, "pf_statetbl_lock");
 	init_pf_mutex();
-	pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME);
 	if (pfattach() < 0) {
-		destroy_dev(pf_dev);
 		destroy_pf_mutex();
 		return (ENOMEM);
 	}
+
 	return (0);
 }
 
@@ -3847,7 +4396,7 @@ pf_unload(void)
 	int error = 0;
 
 	PF_LOCK();
-	pf_status.running = 0;
+	V_pf_status.running = 0;
 	PF_UNLOCK();
 	error = dehook_pf();
 	if (error) {
@@ -3861,18 +4410,18 @@ pf_unload(void)
 	}
 	PF_LOCK();
 	shutdown_pf();
-	pf_end_threads = 1;
-	while (pf_end_threads < 2) {
+	V_pf_end_threads = 1;
+	while (V_pf_end_threads < 2) {
 		wakeup_one(pf_purge_thread);
-		msleep(pf_purge_thread, &pf_task_mtx, 0, "pftmo", hz);
+		msleep(pf_purge_thread, &V_pf_task_mtx, 0, "pftmo", hz);
 	}
 	pfi_cleanup();
 	pf_osfp_flush();
 	pf_osfp_cleanup();
 	cleanup_pf_zone();
 	PF_UNLOCK();
-	destroy_dev(pf_dev);
 	destroy_pf_mutex();
+	sx_destroy(&V_pf_consistency_lock);
 	return error;
 }
 
@@ -3883,11 +4432,10 @@ pf_modevent(module_t mod, int type, void *data)
 
 	switch(type) {
 	case MOD_LOAD:
-		error = pf_load();
+		pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME);
 		break;
-
 	case MOD_UNLOAD:
-		error = pf_unload();
+		destroy_dev(pf_dev);
 		break;
 	default:
 		error = EINVAL;
@@ -3895,7 +4443,7 @@ pf_modevent(module_t mod, int type, void *data)
 	}
 	return error;
 }
-
+ 
 static moduledata_t pf_mod = {
 	"pf",
 	pf_modevent,
@@ -3904,4 +4452,4 @@ static moduledata_t pf_mod = {
 
 DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST);
 MODULE_VERSION(pf, PF_MODVER);
-#endif	/* __FreeBSD__ */
+#endif /* __FreeBSD__ */
diff --git a/sys/contrib/pf/net/pf_lb.c b/sys/contrib/pf/net/pf_lb.c
new file mode 100644
index 0000000..f4c9a00
--- /dev/null
+++ b/sys/contrib/pf/net/pf_lb.c
@@ -0,0 +1,792 @@
+/*	$OpenBSD: pf_lb.c,v 1.2 2009/02/12 02:13:15 sthen Exp $ */
+
+/*
+ * Copyright (c) 2001 Daniel Hartmeier
+ * Copyright (c) 2002 - 2008 Henning Brauer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifdef __FreeBSD__
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include 
+__FBSDID("$FreeBSD$");
+#endif
+
+#ifdef __FreeBSD__
+#include "opt_bpf.h"
+#include "opt_pf.h"
+
+#ifdef DEV_BPF
+#define	NBPFILTER	DEV_BPF
+#else
+#define	NBPFILTER	0
+#endif
+
+#ifdef DEV_PFLOG
+#define	NPFLOG		DEV_PFLOG
+#else
+#define	NPFLOG		0
+#endif
+
+#ifdef DEV_PFSYNC
+#define	NPFSYNC		DEV_PFSYNC
+#else
+#define	NPFSYNC		0
+#endif
+
+#ifdef DEV_PFLOW
+#define	NPFLOW	DEV_PFLOW
+#else
+#define	NPFLOW	0
+#endif
+
+#else
+#include "bpfilter.h"
+#include "pflog.h"
+#include "pfsync.h"
+#include "pflow.h"
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#ifdef  __FreeBSD__
+#include 
+#endif
+#ifndef __FreeBSD__
+#include 
+#endif
+#include 
+#ifdef __FreeBSD__
+#include 
+#include 
+#include 
+#else
+#include 
+#endif
+
+#ifdef __FreeBSD__
+#include 
+#else
+#include 
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef __FreeBSD__
+#include 
+#endif
+#include 
+#include 
+#include 
+
+#if NPFSYNC > 0
+#include 
+#endif /* NPFSYNC > 0 */
+
+#ifdef INET6
+#include 
+#include 
+#include 
+#include 
+#endif /* INET6 */
+
+
+#ifdef __FreeBSD__
+#define DPFPRINTF(n, x)	if (V_pf_status.debug >= (n)) printf x
+#else
+#define DPFPRINTF(n, x)	if (pf_status.debug >= (n)) printf x
+#endif
+
+/*
+ * Global variables
+ */
+
+void			 pf_hash(struct pf_addr *, struct pf_addr *,
+			    struct pf_poolhashkey *, sa_family_t);
+struct pf_rule		*pf_match_translation(struct pf_pdesc *, struct mbuf *,
+			    int, int, struct pfi_kif *,
+			    struct pf_addr *, u_int16_t, struct pf_addr *,
+			    u_int16_t, int);
+int			 pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
+			    struct pf_addr *, struct pf_addr *, u_int16_t,
+			    struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
+			    struct pf_src_node **);
+
+#define mix(a,b,c) \
+	do {					\
+		a -= b; a -= c; a ^= (c >> 13);	\
+		b -= c; b -= a; b ^= (a << 8);	\
+		c -= a; c -= b; c ^= (b >> 13);	\
+		a -= b; a -= c; a ^= (c >> 12);	\
+		b -= c; b -= a; b ^= (a << 16);	\
+		c -= a; c -= b; c ^= (b >> 5);	\
+		a -= b; a -= c; a ^= (c >> 3);	\
+		b -= c; b -= a; b ^= (a << 10);	\
+		c -= a; c -= b; c ^= (b >> 15);	\
+	} while (0)
+
+/*
+ * hash function based on bridge_hash in if_bridge.c
+ */
+void
+pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
+    struct pf_poolhashkey *key, sa_family_t af)
+{
+	u_int32_t	a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
+
+	switch (af) {
+#ifdef INET
+	case AF_INET:
+		a += inaddr->addr32[0];
+		b += key->key32[1];
+		mix(a, b, c);
+		hash->addr32[0] = c + key->key32[2];
+		break;
+#endif /* INET */
+#ifdef INET6
+	case AF_INET6:
+		a += inaddr->addr32[0];
+		b += inaddr->addr32[2];
+		mix(a, b, c);
+		hash->addr32[0] = c;
+		a += inaddr->addr32[1];
+		b += inaddr->addr32[3];
+		c += key->key32[1];
+		mix(a, b, c);
+		hash->addr32[1] = c;
+		a += inaddr->addr32[2];
+		b += inaddr->addr32[1];
+		c += key->key32[2];
+		mix(a, b, c);
+		hash->addr32[2] = c;
+		a += inaddr->addr32[3];
+		b += inaddr->addr32[0];
+		c += key->key32[3];
+		mix(a, b, c);
+		hash->addr32[3] = c;
+		break;
+#endif /* INET6 */
+	}
+}
+
+struct pf_rule *
+pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
+    int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
+    struct pf_addr *daddr, u_int16_t dport, int rs_num)
+{
+	struct pf_rule		*r, *rm = NULL;
+	struct pf_ruleset	*ruleset = NULL;
+	int			 tag = -1;
+	int			 rtableid = -1;
+	int			 asd = 0;
+
+	r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
+	while (r && rm == NULL) {
+		struct pf_rule_addr	*src = NULL, *dst = NULL;
+		struct pf_addr_wrap	*xdst = NULL;
+
+		if (r->action == PF_BINAT && direction == PF_IN) {
+			src = &r->dst;
+			if (r->rpool.cur != NULL)
+				xdst = &r->rpool.cur->addr;
+		} else {
+			src = &r->src;
+			dst = &r->dst;
+		}
+
+		r->evaluations++;
+		if (pfi_kif_match(r->kif, kif) == r->ifnot)
+			r = r->skip[PF_SKIP_IFP].ptr;
+		else if (r->direction && r->direction != direction)
+			r = r->skip[PF_SKIP_DIR].ptr;
+		else if (r->af && r->af != pd->af)
+			r = r->skip[PF_SKIP_AF].ptr;
+		else if (r->proto && r->proto != pd->proto)
+			r = r->skip[PF_SKIP_PROTO].ptr;
+		else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
+		    src->neg, kif))
+			r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
+			    PF_SKIP_DST_ADDR].ptr;
+		else if (src->port_op && !pf_match_port(src->port_op,
+		    src->port[0], src->port[1], sport))
+			r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
+			    PF_SKIP_DST_PORT].ptr;
+		else if (dst != NULL &&
+		    PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL))
+			r = r->skip[PF_SKIP_DST_ADDR].ptr;
+		else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
+		    0, NULL))
+			r = TAILQ_NEXT(r, entries);
+		else if (dst != NULL && dst->port_op &&
+		    !pf_match_port(dst->port_op, dst->port[0],
+		    dst->port[1], dport))
+			r = r->skip[PF_SKIP_DST_PORT].ptr;
+#ifdef __FreeBSD__
+		else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
+#else
+		else if (r->match_tag && !pf_match_tag(m, r, &tag))
+#endif
+			r = TAILQ_NEXT(r, entries);
+		else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
+		    IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
+		    off, pd->hdr.tcp), r->os_fingerprint)))
+			r = TAILQ_NEXT(r, entries);
+		else {
+			if (r->tag)
+				tag = r->tag;
+			if (r->rtableid >= 0)
+				rtableid = r->rtableid;
+			if (r->anchor == NULL) {
+				rm = r;
+			} else
+				pf_step_into_anchor(&asd, &ruleset, rs_num,
+				    &r, NULL, NULL);
+		}
+		if (r == NULL)
+			pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
+			    NULL, NULL);
+	}
+#ifdef __FreeBSD__
+	if (pf_tag_packet(m, tag, rtableid, pd->pf_mtag))
+#else
+	if (pf_tag_packet(m, tag, rtableid))
+#endif
+		return (NULL);
+	if (rm != NULL && (rm->action == PF_NONAT ||
+	    rm->action == PF_NORDR || rm->action == PF_NOBINAT))
+		return (NULL);
+	return (rm);
+}
+
+int
+pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
+    struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
+    struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
+    struct pf_src_node **sn)
+{
+	struct pf_state_key_cmp	key;
+	struct pf_addr		init_addr;
+	u_int16_t		cut;
+
+	bzero(&init_addr, sizeof(init_addr));
+	if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+		return (1);
+
+	if (proto == IPPROTO_ICMP) {
+		low = 1;
+		high = 65535;
+	}
+
+	do {
+		key.af = af;
+		key.proto = proto;
+		PF_ACPY(&key.addr[1], daddr, key.af);
+		PF_ACPY(&key.addr[0], naddr, key.af);
+		key.port[1] = dport;
+
+		/*
+		 * port search; start random, step;
+		 * similar 2 portloop in in_pcbbind
+		 */
+		if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
+		    proto == IPPROTO_ICMP)) {
+			key.port[0] = dport;
+			if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
+				return (0);
+		} else if (low == 0 && high == 0) {
+			key.port[0] = *nport;
+			if (pf_find_state_all(&key, PF_IN, NULL) == NULL)
+				return (0);
+		} else if (low == high) {
+			key.port[0] = htons(low);
+			if (pf_find_state_all(&key, PF_IN, NULL) == NULL) {
+				*nport = htons(low);
+				return (0);
+			}
+		} else {
+			u_int16_t tmp;
+
+			if (low > high) {
+				tmp = low;
+				low = high;
+				high = tmp;
+			}
+			/* low < high */
+#ifdef __FreeBSD__
+			cut = htonl(arc4random()) % (1 + high - low) + low;
+#else
+			cut = arc4random_uniform(1 + high - low) + low;
+#endif
+			/* low <= cut <= high */
+			for (tmp = cut; tmp <= high; ++(tmp)) {
+				key.port[0] = htons(tmp);
+				if (pf_find_state_all(&key, PF_IN, NULL) ==
+#ifdef __FreeBSD__
+				    NULL) {
+#else
+				    NULL && !in_baddynamic(tmp, proto)) {
+#endif
+					*nport = htons(tmp);
+					return (0);
+				}
+			}
+			for (tmp = cut - 1; tmp >= low; --(tmp)) {
+				key.port[0] = htons(tmp);
+				if (pf_find_state_all(&key, PF_IN, NULL) ==
+#ifdef __FreeBSD__
+				    NULL) {
+#else
+				    NULL && !in_baddynamic(tmp, proto)) {
+#endif
+					*nport = htons(tmp);
+					return (0);
+				}
+			}
+		}
+
+		switch (r->rpool.opts & PF_POOL_TYPEMASK) {
+		case PF_POOL_RANDOM:
+		case PF_POOL_ROUNDROBIN:
+			if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+				return (1);
+			break;
+		case PF_POOL_NONE:
+		case PF_POOL_SRCHASH:
+		case PF_POOL_BITMASK:
+		default:
+			return (1);
+		}
+	} while (! PF_AEQ(&init_addr, naddr, af) );
+	return (1);					/* none available */
+}
+
+int
+pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
+    struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
+{
+	unsigned char		 hash[16];
+	struct pf_pool		*rpool = &r->rpool;
+	struct pf_addr		*raddr = &rpool->cur->addr.v.a.addr;
+	struct pf_addr		*rmask = &rpool->cur->addr.v.a.mask;
+	struct pf_pooladdr	*acur = rpool->cur;
+	struct pf_src_node	 k;
+
+	if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
+	    (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
+		k.af = af;
+		PF_ACPY(&k.addr, saddr, af);
+		if (r->rule_flag & PFRULE_RULESRCTRACK ||
+		    r->rpool.opts & PF_POOL_STICKYADDR)
+			k.rule.ptr = r;
+		else
+			k.rule.ptr = NULL;
+#ifdef __FreeBSD__
+		V_pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
+		*sn = RB_FIND(pf_src_tree, &V_tree_src_tracking, &k);
+#else
+		pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
+		*sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
+#endif
+		if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
+			PF_ACPY(naddr, &(*sn)->raddr, af);
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
+			if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
+				printf("pf_map_addr: src tracking maps ");
+				pf_print_host(&k.addr, 0, af);
+				printf(" to ");
+				pf_print_host(naddr, 0, af);
+				printf("\n");
+			}
+			return (0);
+		}
+	}
+
+	if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
+		return (1);
+	if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+		switch (af) {
+#ifdef INET
+		case AF_INET:
+			if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
+			    (rpool->opts & PF_POOL_TYPEMASK) !=
+			    PF_POOL_ROUNDROBIN)
+				return (1);
+			 raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
+			 rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
+			break;
+#endif /* INET */
+#ifdef INET6
+		case AF_INET6:
+			if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
+			    (rpool->opts & PF_POOL_TYPEMASK) !=
+			    PF_POOL_ROUNDROBIN)
+				return (1);
+			raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
+			rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
+			break;
+#endif /* INET6 */
+		}
+	} else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+		if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
+			return (1); /* unsupported */
+	} else {
+		raddr = &rpool->cur->addr.v.a.addr;
+		rmask = &rpool->cur->addr.v.a.mask;
+	}
+
+	switch (rpool->opts & PF_POOL_TYPEMASK) {
+	case PF_POOL_NONE:
+		PF_ACPY(naddr, raddr, af);
+		break;
+	case PF_POOL_BITMASK:
+		PF_POOLMASK(naddr, raddr, rmask, saddr, af);
+		break;
+	case PF_POOL_RANDOM:
+		if (init_addr != NULL && PF_AZERO(init_addr, af)) {
+			switch (af) {
+#ifdef INET
+			case AF_INET:
+				rpool->counter.addr32[0] = htonl(arc4random());
+				break;
+#endif /* INET */
+#ifdef INET6
+			case AF_INET6:
+				if (rmask->addr32[3] != 0xffffffff)
+					rpool->counter.addr32[3] =
+					    htonl(arc4random());
+				else
+					break;
+				if (rmask->addr32[2] != 0xffffffff)
+					rpool->counter.addr32[2] =
+					    htonl(arc4random());
+				else
+					break;
+				if (rmask->addr32[1] != 0xffffffff)
+					rpool->counter.addr32[1] =
+					    htonl(arc4random());
+				else
+					break;
+				if (rmask->addr32[0] != 0xffffffff)
+					rpool->counter.addr32[0] =
+					    htonl(arc4random());
+				break;
+#endif /* INET6 */
+			}
+			PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
+			PF_ACPY(init_addr, naddr, af);
+
+		} else {
+			PF_AINC(&rpool->counter, af);
+			PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
+		}
+		break;
+	case PF_POOL_SRCHASH:
+		pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
+		PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
+		break;
+	case PF_POOL_ROUNDROBIN:
+		if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+			if (!pfr_pool_get(rpool->cur->addr.p.tbl,
+			    &rpool->tblidx, &rpool->counter,
+			    &raddr, &rmask, af))
+				goto get_addr;
+		} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+			if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
+			    &rpool->tblidx, &rpool->counter,
+			    &raddr, &rmask, af))
+				goto get_addr;
+		} else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
+			goto get_addr;
+
+	try_next:
+		if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL)
+			rpool->cur = TAILQ_FIRST(&rpool->list);
+		if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+			rpool->tblidx = -1;
+			if (pfr_pool_get(rpool->cur->addr.p.tbl,
+			    &rpool->tblidx, &rpool->counter,
+			    &raddr, &rmask, af)) {
+				/* table contains no address of type 'af' */
+				if (rpool->cur != acur)
+					goto try_next;
+				return (1);
+			}
+		} else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+			rpool->tblidx = -1;
+			if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
+			    &rpool->tblidx, &rpool->counter,
+			    &raddr, &rmask, af)) {
+				/* table contains no address of type 'af' */
+				if (rpool->cur != acur)
+					goto try_next;
+				return (1);
+			}
+		} else {
+			raddr = &rpool->cur->addr.v.a.addr;
+			rmask = &rpool->cur->addr.v.a.mask;
+			PF_ACPY(&rpool->counter, raddr, af);
+		}
+
+	get_addr:
+		PF_ACPY(naddr, &rpool->counter, af);
+		if (init_addr != NULL && PF_AZERO(init_addr, af))
+			PF_ACPY(init_addr, naddr, af);
+		PF_AINC(&rpool->counter, af);
+		break;
+	}
+	if (*sn != NULL)
+		PF_ACPY(&(*sn)->raddr, naddr, af);
+
+#ifdef __FreeBSD__
+	if (V_pf_status.debug >= PF_DEBUG_MISC &&
+#else
+	if (pf_status.debug >= PF_DEBUG_MISC &&
+#endif
+	    (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
+		printf("pf_map_addr: selected address ");
+		pf_print_host(naddr, 0, af);
+		printf("\n");
+	}
+
+	return (0);
+}
+
+struct pf_rule *
+pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
+    struct pfi_kif *kif, struct pf_src_node **sn,
+    struct pf_state_key **skw, struct pf_state_key **sks,
+    struct pf_state_key **skp, struct pf_state_key **nkp,
+    struct pf_addr *saddr, struct pf_addr *daddr,
+    u_int16_t sport, u_int16_t dport)
+{
+	struct pf_rule	*r = NULL;
+
+
+	if (direction == PF_OUT) {
+		r = pf_match_translation(pd, m, off, direction, kif, saddr,
+		    sport, daddr, dport, PF_RULESET_BINAT);
+		if (r == NULL)
+			r = pf_match_translation(pd, m, off, direction, kif,
+			    saddr, sport, daddr, dport, PF_RULESET_NAT);
+	} else {
+		r = pf_match_translation(pd, m, off, direction, kif, saddr,
+		    sport, daddr, dport, PF_RULESET_RDR);
+		if (r == NULL)
+			r = pf_match_translation(pd, m, off, direction, kif,
+			    saddr, sport, daddr, dport, PF_RULESET_BINAT);
+	}
+
+	if (r != NULL) {
+		struct pf_addr	*naddr;
+		u_int16_t	*nport;
+
+		if (pf_state_key_setup(pd, r, skw, sks, skp, nkp,
+		    saddr, daddr, sport, dport))
+			return r;
+
+		/* XXX We only modify one side for now. */
+		naddr = &(*nkp)->addr[1];
+		nport = &(*nkp)->port[1];
+
+		switch (r->action) {
+		case PF_NONAT:
+		case PF_NOBINAT:
+		case PF_NORDR:
+			return (NULL);
+		case PF_NAT:
+			if (pf_get_sport(pd->af, pd->proto, r, saddr,
+			    daddr, dport, naddr, nport, r->rpool.proxy_port[0],
+			    r->rpool.proxy_port[1], sn)) {
+				DPFPRINTF(PF_DEBUG_MISC,
+				    ("pf: NAT proxy port allocation "
+				    "(%u-%u) failed\n",
+				    r->rpool.proxy_port[0],
+				    r->rpool.proxy_port[1]));
+				return (NULL);
+			}
+			break;
+		case PF_BINAT:
+			switch (direction) {
+			case PF_OUT:
+				if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
+					switch (pd->af) {
+#ifdef INET
+					case AF_INET:
+						if (r->rpool.cur->addr.p.dyn->
+						    pfid_acnt4 < 1)
+							return (NULL);
+						PF_POOLMASK(naddr,
+						    &r->rpool.cur->addr.p.dyn->
+						    pfid_addr4,
+						    &r->rpool.cur->addr.p.dyn->
+						    pfid_mask4,
+						    saddr, AF_INET);
+						break;
+#endif /* INET */
+#ifdef INET6
+					case AF_INET6:
+						if (r->rpool.cur->addr.p.dyn->
+						    pfid_acnt6 < 1)
+							return (NULL);
+						PF_POOLMASK(naddr,
+						    &r->rpool.cur->addr.p.dyn->
+						    pfid_addr6,
+						    &r->rpool.cur->addr.p.dyn->
+						    pfid_mask6,
+						    saddr, AF_INET6);
+						break;
+#endif /* INET6 */
+					}
+				} else
+					PF_POOLMASK(naddr,
+					    &r->rpool.cur->addr.v.a.addr,
+					    &r->rpool.cur->addr.v.a.mask,
+					    saddr, pd->af);
+				break;
+			case PF_IN:
+				if (r->src.addr.type == PF_ADDR_DYNIFTL) {
+					switch (pd->af) {
+#ifdef INET
+					case AF_INET:
+						if (r->src.addr.p.dyn->
+						    pfid_acnt4 < 1)
+							return (NULL);
+						PF_POOLMASK(naddr,
+						    &r->src.addr.p.dyn->
+						    pfid_addr4,
+						    &r->src.addr.p.dyn->
+						    pfid_mask4,
+						    daddr, AF_INET);
+						break;
+#endif /* INET */
+#ifdef INET6
+					case AF_INET6:
+						if (r->src.addr.p.dyn->
+						    pfid_acnt6 < 1)
+							return (NULL);
+						PF_POOLMASK(naddr,
+						    &r->src.addr.p.dyn->
+						    pfid_addr6,
+						    &r->src.addr.p.dyn->
+						    pfid_mask6,
+						    daddr, AF_INET6);
+						break;
+#endif /* INET6 */
+					}
+				} else
+					PF_POOLMASK(naddr,
+					    &r->src.addr.v.a.addr,
+					    &r->src.addr.v.a.mask, daddr,
+					    pd->af);
+				break;
+			}
+			break;
+		case PF_RDR: {
+			if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
+				return (NULL);
+			if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
+			    PF_POOL_BITMASK)
+				PF_POOLMASK(naddr, naddr,
+				    &r->rpool.cur->addr.v.a.mask, daddr,
+				    pd->af);
+
+			if (r->rpool.proxy_port[1]) {
+				u_int32_t	tmp_nport;
+
+				tmp_nport = ((ntohs(dport) -
+				    ntohs(r->dst.port[0])) %
+				    (r->rpool.proxy_port[1] -
+				    r->rpool.proxy_port[0] + 1)) +
+				    r->rpool.proxy_port[0];
+
+				/* wrap around if necessary */
+				if (tmp_nport > 65535)
+					tmp_nport -= 65535;
+				*nport = htons((u_int16_t)tmp_nport);
+			} else if (r->rpool.proxy_port[0])
+				*nport = htons(r->rpool.proxy_port[0]);
+			break;
+		}
+		default:
+			return (NULL);
+		}
+		/* 
+		 * Translation was a NOP.
+		 * Pretend there was no match.
+		 */
+		if (!bcmp(*skp, *nkp, sizeof(struct pf_state_key_cmp))) {
+#ifdef __FreeBSD__
+			pool_put(&V_pf_state_key_pl, *nkp);
+			pool_put(&V_pf_state_key_pl, *skp);
+#else
+			pool_put(&pf_state_key_pl, *nkp);
+			pool_put(&pf_state_key_pl, *skp);
+#endif
+			*skw = *sks = *nkp = *skp = NULL;
+			return (NULL);
+		}
+	}
+
+	return (r);
+}
+
diff --git a/sys/contrib/pf/net/pf_mtag.h b/sys/contrib/pf/net/pf_mtag.h
index a0ebf7e..141a867 100644
--- a/sys/contrib/pf/net/pf_mtag.h
+++ b/sys/contrib/pf/net/pf_mtag.h
@@ -37,15 +37,17 @@
 #define	PF_TAG_GENERATED		0x01
 #define	PF_TAG_FRAGCACHE		0x02
 #define	PF_TAG_TRANSLATE_LOCALHOST	0x04
+#define	PF_PACKET_LOOPED		0x08
+#define	PF_FASTFWD_OURS_PRESENT		0x10
 
 struct pf_mtag {
 	void		*hdr;		/* saved hdr pos in mbuf, for ECN */
-	u_int		 rtableid;	/* alternate routing table id */
+	void		*statekey;	/* pf stackside statekey */
 	u_int32_t	 qid;		/* queue id */
+	u_int		 rtableid;	/* alternate routing table id */
 	u_int16_t	 tag;		/* tag id */
 	u_int8_t	 flags;
 	u_int8_t	 routed;
-	sa_family_t	 af;		/* for ECN */
 };
 
 static __inline struct pf_mtag *pf_find_mtag(struct mbuf *);
diff --git a/sys/contrib/pf/net/pf_norm.c b/sys/contrib/pf/net/pf_norm.c
index cd6d65a..6c04eee 100644
--- a/sys/contrib/pf/net/pf_norm.c
+++ b/sys/contrib/pf/net/pf_norm.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf_norm.c,v 1.107 2006/04/16 00:59:52 pascoe Exp $ */
+/*	$OpenBSD: pf_norm.c,v 1.114 2009/01/29 14:11:45 henning Exp $ */
 
 /*
  * Copyright 2001 Niels Provos 
@@ -34,9 +34,9 @@
 __FBSDID("$FreeBSD$");
 
 #ifdef DEV_PFLOG
-#define	NPFLOG DEV_PFLOG
+#define	NPFLOG	DEV_PFLOG
 #else
-#define	NPFLOG 0
+#define	NPFLOG	0
 #endif
 #else
 #include "pflog.h"
@@ -78,8 +78,6 @@ __FBSDID("$FreeBSD$");
 #include 
 
 #ifndef __FreeBSD__
-#include 
-
 struct pf_frent {
 	LIST_ENTRY(pf_frent) fr_next;
 	struct ip *fr_ip;
@@ -118,17 +116,35 @@ struct pf_fragment {
 };
 #endif
 
+#ifdef __FreeBSD__
+TAILQ_HEAD(pf_fragqueue, pf_fragment);
+TAILQ_HEAD(pf_cachequeue, pf_fragment);
+VNET_DEFINE(struct pf_fragqueue,	pf_fragqueue);
+#define	V_pf_fragqueue			VNET(pf_fragqueue)
+VNET_DEFINE(struct pf_cachequeue,	pf_cachequeue);
+#define	V_pf_cachequeue			VNET(pf_cachequeue)
+#else
 TAILQ_HEAD(pf_fragqueue, pf_fragment)	pf_fragqueue;
 TAILQ_HEAD(pf_cachequeue, pf_fragment)	pf_cachequeue;
+#endif
 
 #ifndef __FreeBSD__
 static __inline int	 pf_frag_compare(struct pf_fragment *,
 			    struct pf_fragment *);
 #else
-static int	 pf_frag_compare(struct pf_fragment *,
+static int		 pf_frag_compare(struct pf_fragment *,
 			    struct pf_fragment *);
 #endif
+
+#ifdef __FreeBSD__
+RB_HEAD(pf_frag_tree, pf_fragment);
+VNET_DEFINE(struct pf_frag_tree,	pf_frag_tree);
+#define	V_pf_frag_tree			VNET(pf_frag_tree)
+VNET_DEFINE(struct pf_frag_tree,	pf_cache_tree);
+#define	V_pf_cache_tree			VNET(pf_cache_tree)
+#else
 RB_HEAD(pf_frag_tree, pf_fragment)	pf_frag_tree, pf_cache_tree;
+#endif
 RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
 RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
 
@@ -143,24 +159,45 @@ struct mbuf		*pf_reassemble(struct mbuf **, struct pf_fragment **,
 struct mbuf		*pf_fragcache(struct mbuf **, struct ip*,
 			    struct pf_fragment **, int, int, int *);
 int			 pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
-			    struct tcphdr *, int);
-
+			    struct tcphdr *, int, sa_family_t);
+void			 pf_scrub_ip(struct mbuf **, u_int32_t, u_int8_t,
+			    u_int8_t);
+#ifdef INET6
+void			 pf_scrub_ip6(struct mbuf **, u_int8_t);
+#endif
+#ifdef __FreeBSD__
+#define	DPFPRINTF(x) do {				\
+	if (V_pf_status.debug >= PF_DEBUG_MISC) {	\
+		printf("%s: ", __func__);		\
+		printf x ;				\
+	}						\
+} while(0)
+#else
 #define	DPFPRINTF(x) do {				\
 	if (pf_status.debug >= PF_DEBUG_MISC) {		\
 		printf("%s: ", __func__);		\
 		printf x ;				\
 	}						\
 } while(0)
+#endif
 
 /* Globals */
 #ifdef __FreeBSD__
-uma_zone_t		 pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
-uma_zone_t		 pf_state_scrub_pl;
+VNET_DEFINE(uma_zone_t,		pf_frent_pl);
+VNET_DEFINE(uma_zone_t,		pf_frag_pl);
+VNET_DEFINE(uma_zone_t,		pf_cache_pl);
+VNET_DEFINE(uma_zone_t,		pf_cent_pl);
+VNET_DEFINE(uma_zone_t,		pf_state_scrub_pl);
+
+VNET_DEFINE(int,		pf_nfrents);
+#define	V_pf_nfrents		VNET(pf_nfrents)
+VNET_DEFINE(int,		pf_ncache);
+#define	V_pf_ncache		VNET(pf_ncache)
 #else
 struct pool		 pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
 struct pool		 pf_state_scrub_pl;
-#endif
 int			 pf_nfrents, pf_ncache;
+#endif
 
 void
 pf_normalize_init(void)
@@ -171,9 +208,9 @@ pf_normalize_init(void)
 	 * No high water mark support(It's hint not hard limit).
 	 * uma_zone_set_max(pf_frag_pl, PFFRAG_FRAG_HIWAT);
 	 */
-	uma_zone_set_max(pf_frent_pl, PFFRAG_FRENT_HIWAT);
-	uma_zone_set_max(pf_cache_pl, PFFRAG_FRCACHE_HIWAT);
-	uma_zone_set_max(pf_cent_pl, PFFRAG_FRCENT_HIWAT);
+	uma_zone_set_max(V_pf_frent_pl, PFFRAG_FRENT_HIWAT);
+	uma_zone_set_max(V_pf_cache_pl, PFFRAG_FRCACHE_HIWAT);
+	uma_zone_set_max(V_pf_cent_pl, PFFRAG_FRCENT_HIWAT);
 #else
 	pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
 	    NULL);
@@ -192,8 +229,13 @@ pf_normalize_init(void)
 	pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0);
 #endif
 
+#ifdef __FreeBSD__
+	TAILQ_INIT(&V_pf_fragqueue);
+	TAILQ_INIT(&V_pf_cachequeue);
+#else
 	TAILQ_INIT(&pf_fragqueue);
 	TAILQ_INIT(&pf_cachequeue);
+#endif
 }
 
 #ifdef __FreeBSD__
@@ -224,14 +266,20 @@ void
 pf_purge_expired_fragments(void)
 {
 	struct pf_fragment	*frag;
+#ifdef __FreeBSD__
+	u_int32_t		 expire = time_second -
+				    V_pf_default_rule.timeout[PFTM_FRAG];
+#else
 	u_int32_t		 expire = time_second -
 				    pf_default_rule.timeout[PFTM_FRAG];
+#endif
 
-	while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
 #ifdef __FreeBSD__
+	while ((frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue)) != NULL) {
 		KASSERT((BUFFER_FRAGMENTS(frag)),
-			("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__));
+		    ("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__));
 #else
+	while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
 		KASSERT(BUFFER_FRAGMENTS(frag));
 #endif
 		if (frag->fr_timeout > expire)
@@ -241,11 +289,12 @@ pf_purge_expired_fragments(void)
 		pf_free_fragment(frag);
 	}
 
-	while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
 #ifdef __FreeBSD__
+	while ((frag = TAILQ_LAST(&V_pf_cachequeue, pf_cachequeue)) != NULL) {
 		KASSERT((!BUFFER_FRAGMENTS(frag)),
-			("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__));
+		    ("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__));
 #else
+	while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
 		KASSERT(!BUFFER_FRAGMENTS(frag));
 #endif
 		if (frag->fr_timeout > expire)
@@ -254,8 +303,8 @@ pf_purge_expired_fragments(void)
 		DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
 		pf_free_fragment(frag);
 #ifdef __FreeBSD__
-		KASSERT((TAILQ_EMPTY(&pf_cachequeue) ||
-		    TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag),
+		KASSERT((TAILQ_EMPTY(&V_pf_cachequeue) ||
+		    TAILQ_LAST(&V_pf_cachequeue, pf_cachequeue) != frag),
 		    ("!(TAILQ_EMPTY() || TAILQ_LAST() == farg): %s",
 		    __FUNCTION__));
 #else
@@ -275,22 +324,44 @@ pf_flush_fragments(void)
 	struct pf_fragment	*frag;
 	int			 goal;
 
+#ifdef __FreeBSD__
+	goal = V_pf_nfrents * 9 / 10;
+	DPFPRINTF(("trying to free > %d frents\n",
+	    V_pf_nfrents - goal));
+	while (goal < V_pf_nfrents) {
+#else
 	goal = pf_nfrents * 9 / 10;
 	DPFPRINTF(("trying to free > %d frents\n",
 	    pf_nfrents - goal));
 	while (goal < pf_nfrents) {
+#endif
+#ifdef __FreeBSD__
+		frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue);
+#else
 		frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue);
+#endif
 		if (frag == NULL)
 			break;
 		pf_free_fragment(frag);
 	}
 
 
+#ifdef __FreeBSD__
+	goal = V_pf_ncache * 9 / 10;
+	DPFPRINTF(("trying to free > %d cache entries\n",
+	    V_pf_ncache - goal));
+	while (goal < V_pf_ncache) {
+#else
 	goal = pf_ncache * 9 / 10;
 	DPFPRINTF(("trying to free > %d cache entries\n",
 	    pf_ncache - goal));
 	while (goal < pf_ncache) {
+#endif
+#ifdef __FreeBSD__
+		frag = TAILQ_LAST(&V_pf_cachequeue, pf_cachequeue);
+#else
 		frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue);
+#endif
 		if (frag == NULL)
 			break;
 		pf_free_fragment(frag);
@@ -312,8 +383,13 @@ pf_free_fragment(struct pf_fragment *frag)
 			LIST_REMOVE(frent, fr_next);
 
 			m_freem(frent->fr_m);
+#ifdef __FreeBSD__
+			pool_put(&V_pf_frent_pl, frent);
+			V_pf_nfrents--;
+#else
 			pool_put(&pf_frent_pl, frent);
 			pf_nfrents--;
+#endif
 		}
 	} else {
 		for (frcache = LIST_FIRST(&frag->fr_cache); frcache;
@@ -325,15 +401,18 @@ pf_free_fragment(struct pf_fragment *frag)
 			    LIST_FIRST(&frag->fr_cache)->fr_off >
 			    frcache->fr_end),
 			    ("! (LIST_EMPTY() || LIST_FIRST()->fr_off >"
-                             " frcache->fr_end): %s", __FUNCTION__));
+			      " frcache->fr_end): %s", __FUNCTION__));
+
+			pool_put(&V_pf_cent_pl, frcache);
+			V_pf_ncache--;
 #else
 			KASSERT(LIST_EMPTY(&frag->fr_cache) ||
 			    LIST_FIRST(&frag->fr_cache)->fr_off >
 			    frcache->fr_end);
-#endif
 
 			pool_put(&pf_cent_pl, frcache);
 			pf_ncache--;
+#endif
 		}
 	}
 
@@ -362,11 +441,21 @@ pf_find_fragment(struct ip *ip, struct pf_frag_tree *tree)
 		/* XXX Are we sure we want to update the timeout? */
 		frag->fr_timeout = time_second;
 		if (BUFFER_FRAGMENTS(frag)) {
+#ifdef __FreeBSD__
+			TAILQ_REMOVE(&V_pf_fragqueue, frag, frag_next);
+			TAILQ_INSERT_HEAD(&V_pf_fragqueue, frag, frag_next);
+#else
 			TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
 			TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
+#endif
 		} else {
+#ifdef __FreeBSD__
+			TAILQ_REMOVE(&V_pf_cachequeue, frag, frag_next);
+			TAILQ_INSERT_HEAD(&V_pf_cachequeue, frag, frag_next);
+#else
 			TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
 			TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next);
+#endif
 		}
 	}
 
@@ -379,13 +468,25 @@ void
 pf_remove_fragment(struct pf_fragment *frag)
 {
 	if (BUFFER_FRAGMENTS(frag)) {
+#ifdef __FreeBSD__
+		RB_REMOVE(pf_frag_tree, &V_pf_frag_tree, frag);
+		TAILQ_REMOVE(&V_pf_fragqueue, frag, frag_next);
+		pool_put(&V_pf_frag_pl, frag);
+#else
 		RB_REMOVE(pf_frag_tree, &pf_frag_tree, frag);
 		TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
 		pool_put(&pf_frag_pl, frag);
+#endif
 	} else {
+#ifdef __FreeBSD__
+		RB_REMOVE(pf_frag_tree, &V_pf_cache_tree, frag);
+		TAILQ_REMOVE(&V_pf_cachequeue, frag, frag_next);
+		pool_put(&V_pf_cache_pl, frag);
+#else
 		RB_REMOVE(pf_frag_tree, &pf_cache_tree, frag);
 		TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
 		pool_put(&pf_cache_pl, frag);
+#endif
 	}
 }
 
@@ -416,10 +517,18 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
 
 	/* Create a new reassembly queue for this packet */
 	if (*frag == NULL) {
+#ifdef __FreeBSD__
+		*frag = pool_get(&V_pf_frag_pl, PR_NOWAIT);
+#else
 		*frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+#endif
 		if (*frag == NULL) {
 			pf_flush_fragments();
+#ifdef __FreeBSD__
+			*frag = pool_get(&V_pf_frag_pl, PR_NOWAIT);
+#else
 			*frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+#endif
 			if (*frag == NULL)
 				goto drop_fragment;
 		}
@@ -433,8 +542,13 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
 		(*frag)->fr_timeout = time_second;
 		LIST_INIT(&(*frag)->fr_queue);
 
+#ifdef __FreeBSD__
+		RB_INSERT(pf_frag_tree, &V_pf_frag_tree, *frag);
+		TAILQ_INSERT_HEAD(&V_pf_fragqueue, *frag, frag_next);
+#else
 		RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
 		TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next);
+#endif
 
 		/* We do not have a previous fragment */
 		frep = NULL;
@@ -499,8 +613,13 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
 		next = LIST_NEXT(frea, fr_next);
 		m_freem(frea->fr_m);
 		LIST_REMOVE(frea, fr_next);
+#ifdef __FreeBSD__
+		pool_put(&V_pf_frent_pl, frea);
+		V_pf_nfrents--;
+#else
 		pool_put(&pf_frent_pl, frea);
 		pf_nfrents--;
+#endif
 	}
 
  insert:
@@ -560,26 +679,36 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
 	m2 = m->m_next;
 	m->m_next = NULL;
 	m_cat(m, m2);
+#ifdef __FreeBSD__
+	pool_put(&V_pf_frent_pl, frent);
+	V_pf_nfrents--;
+#else
 	pool_put(&pf_frent_pl, frent);
 	pf_nfrents--;
+#endif
 	for (frent = next; frent != NULL; frent = next) {
 		next = LIST_NEXT(frent, fr_next);
 
 		m2 = frent->fr_m;
+#ifdef __FreeBSD__
+		pool_put(&V_pf_frent_pl, frent);
+		V_pf_nfrents--;
+#else
 		pool_put(&pf_frent_pl, frent);
 		pf_nfrents--;
+#endif
 #ifdef __FreeBSD__
 		m->m_pkthdr.csum_flags &= m2->m_pkthdr.csum_flags;
 		m->m_pkthdr.csum_data += m2->m_pkthdr.csum_data;
 #endif
 		m_cat(m, m2);
 	}
+
 #ifdef __FreeBSD__
 	while (m->m_pkthdr.csum_data & 0xffff0000)
 		m->m_pkthdr.csum_data = (m->m_pkthdr.csum_data & 0xffff) +
 		    (m->m_pkthdr.csum_data >> 16);
 #endif
-
 	ip->ip_src = (*frag)->fr_src;
 	ip->ip_dst = (*frag)->fr_dst;
 
@@ -606,8 +735,13 @@ pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
 
  drop_fragment:
 	/* Oops - fail safe - drop packet */
+#ifdef __FreeBSD__
+	pool_put(&V_pf_frent_pl, frent);
+	V_pf_nfrents--;
+#else
 	pool_put(&pf_frent_pl, frent);
 	pf_nfrents--;
+#endif
 	m_freem(m);
 	return (NULL);
 }
@@ -632,22 +766,40 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
 
 	/* Create a new range queue for this packet */
 	if (*frag == NULL) {
+#ifdef __FreeBSD__
+		*frag = pool_get(&V_pf_cache_pl, PR_NOWAIT);
+#else
 		*frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+#endif
 		if (*frag == NULL) {
 			pf_flush_fragments();
+#ifdef __FreeBSD__
+			*frag = pool_get(&V_pf_cache_pl, PR_NOWAIT);
+#else
 			*frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+#endif
 			if (*frag == NULL)
 				goto no_mem;
 		}
 
 		/* Get an entry for the queue */
+#ifdef __FreeBSD__
+		cur = pool_get(&V_pf_cent_pl, PR_NOWAIT);
+		if (cur == NULL) {
+			pool_put(&V_pf_cache_pl, *frag);
+#else
 		cur = pool_get(&pf_cent_pl, PR_NOWAIT);
 		if (cur == NULL) {
 			pool_put(&pf_cache_pl, *frag);
+#endif
 			*frag = NULL;
 			goto no_mem;
 		}
+#ifdef __FreeBSD__
+		V_pf_ncache++;
+#else
 		pf_ncache++;
+#endif
 
 		(*frag)->fr_flags = PFFRAG_NOBUFFER;
 		(*frag)->fr_max = 0;
@@ -662,8 +814,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
 		LIST_INIT(&(*frag)->fr_cache);
 		LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
 
+#ifdef __FreeBSD__
+		RB_INSERT(pf_frag_tree, &V_pf_cache_tree, *frag);
+		TAILQ_INSERT_HEAD(&V_pf_cachequeue, *frag, frag_next);
+#else
 		RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
 		TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);
+#endif
 
 		DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max));
 
@@ -782,10 +939,18 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
 			    h->ip_id, -precut, frp->fr_off, frp->fr_end, off,
 			    max));
 
+#ifdef __FreeBSD__
+			cur = pool_get(&V_pf_cent_pl, PR_NOWAIT);
+#else
 			cur = pool_get(&pf_cent_pl, PR_NOWAIT);
+#endif
 			if (cur == NULL)
 				goto no_mem;
+#ifdef __FreeBSD__
+			V_pf_ncache++;
+#else
 			pf_ncache++;
+#endif
 
 			cur->fr_off = off;
 			cur->fr_end = max;
@@ -842,10 +1007,18 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
 			    h->ip_id, -aftercut, off, max, fra->fr_off,
 			    fra->fr_end));
 
+#ifdef __FreeBSD__
+			cur = pool_get(&V_pf_cent_pl, PR_NOWAIT);
+#else
 			cur = pool_get(&pf_cent_pl, PR_NOWAIT);
+#endif
 			if (cur == NULL)
 				goto no_mem;
+#ifdef __FreeBSD__
+			V_pf_ncache++;
+#else
 			pf_ncache++;
+#endif
 
 			cur->fr_off = off;
 			cur->fr_end = max;
@@ -863,8 +1036,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
 				    max, fra->fr_off, fra->fr_end));
 				fra->fr_off = cur->fr_off;
 				LIST_REMOVE(cur, fr_next);
+#ifdef __FreeBSD__
+				pool_put(&V_pf_cent_pl, cur);
+				V_pf_ncache--;
+#else
 				pool_put(&pf_cent_pl, cur);
 				pf_ncache--;
+#endif
 				cur = NULL;
 
 			} else if (frp && fra->fr_off <= frp->fr_end) {
@@ -881,8 +1059,13 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
 				    max, fra->fr_off, fra->fr_end));
 				fra->fr_off = frp->fr_off;
 				LIST_REMOVE(frp, fr_next);
+#ifdef __FreeBSD__
+				pool_put(&V_pf_cent_pl, frp);
+				V_pf_ncache--;
+#else
 				pool_put(&pf_cent_pl, frp);
 				pf_ncache--;
+#endif
 				frp = NULL;
 
 			}
@@ -965,6 +1148,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 	u_int16_t		 max;
 	int			 ip_len;
 	int			 ip_off;
+	int			 tag = -1;
 
 	r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
 	while (r != NULL) {
@@ -985,6 +1169,12 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 		    (struct pf_addr *)&h->ip_dst.s_addr, AF_INET,
 		    r->dst.neg, NULL))
 			r = r->skip[PF_SKIP_DST_ADDR].ptr;
+#ifdef __FreeBSD__
+		else if (r->match_tag && !pf_match_tag(m, r, &tag, pd->pf_mtag))
+#else
+		else if (r->match_tag && !pf_match_tag(m, r, &tag))
+#endif
+			r = TAILQ_NEXT(r, entries);
 		else
 			break;
 	}
@@ -1043,7 +1233,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 	if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0) {
 		/* Fully buffer all of the fragments */
 
+#ifdef __FreeBSD__
+		frag = pf_find_fragment(h, &V_pf_frag_tree);
+#else
 		frag = pf_find_fragment(h, &pf_frag_tree);
+#endif
 
 		/* Check if we saw the last fragment already */
 		if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
@@ -1051,12 +1245,20 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 			goto bad;
 
 		/* Get an entry for the fragment queue */
+#ifdef __FreeBSD__
+		frent = pool_get(&V_pf_frent_pl, PR_NOWAIT);
+#else
 		frent = pool_get(&pf_frent_pl, PR_NOWAIT);
+#endif
 		if (frent == NULL) {
 			REASON_SET(reason, PFRES_MEMORY);
 			return (PF_DROP);
 		}
+#ifdef __FreeBSD__
+		V_pf_nfrents++;
+#else
 		pf_nfrents++;
+#endif
 		frent->fr_ip = h;
 		frent->fr_m = m;
 
@@ -1087,7 +1289,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 		/* non-buffering fragment cache (drops or masks overlaps) */
 		int	nomem = 0;
 
+#ifdef __FreeBSD__
 		if (dir == PF_OUT && pd->pf_mtag->flags & PF_TAG_FRAGCACHE) {
+#else
+		if (dir == PF_OUT && m->m_pkthdr.pf.flags & PF_TAG_FRAGCACHE) {
+#endif
 			/*
 			 * Already passed the fragment cache in the
 			 * input direction.  If we continued, it would
@@ -1096,7 +1302,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 			goto fragment_pass;
 		}
 
+#ifdef __FreeBSD__
+		frag = pf_find_fragment(h, &V_pf_cache_tree);
+#else
 		frag = pf_find_fragment(h, &pf_cache_tree);
+#endif
 
 		/* Check if we saw the last fragment already */
 		if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
@@ -1127,7 +1337,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 		}
 #endif
 		if (dir == PF_IN)
+#ifdef __FreeBSD__
 			pd->pf_mtag->flags |= PF_TAG_FRAGCACHE;
+#else
+			m->m_pkthdr.pf.flags |= PF_TAG_FRAGCACHE;
+#endif
 
 		if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
 			goto drop;
@@ -1143,33 +1357,11 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
 		h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
 	}
 
-	/* Enforce a minimum ttl, may cause endless packet loops */
-	if (r->min_ttl && h->ip_ttl < r->min_ttl) {
-		u_int16_t ip_ttl = h->ip_ttl;
-
-		h->ip_ttl = r->min_ttl;
-		h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
-	}
-
-	if (r->rule_flag & PFRULE_RANDOMID) {
-		u_int16_t ip_id = h->ip_id;
-
-		h->ip_id = ip_randomid();
-		h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0);
-	}
-	if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
-		pd->flags |= PFDESC_IP_REAS;
-
-	return (PF_PASS);
+	/* not missing a return here */
 
  fragment_pass:
-	/* Enforce a minimum ttl, may cause endless packet loops */
-	if (r->min_ttl && h->ip_ttl < r->min_ttl) {
-		u_int16_t ip_ttl = h->ip_ttl;
+	pf_scrub_ip(&m, r->rule_flag, r->min_ttl, r->set_tos);
 
-		h->ip_ttl = r->min_ttl;
-		h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
-	}
 	if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
 		pd->flags |= PFDESC_IP_REAS;
 	return (PF_PASS);
@@ -1339,9 +1531,7 @@ pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
 	if (sizeof(struct ip6_hdr) + plen > m->m_pkthdr.len)
 		goto shortpkt;
 
-	/* Enforce a minimum ttl, may cause endless packet loops */
-	if (r->min_ttl && h->ip6_hlim < r->min_ttl)
-		h->ip6_hlim = r->min_ttl;
+	pf_scrub_ip6(&m, r->min_ttl);
 
 	return (PF_PASS);
 
@@ -1479,12 +1669,16 @@ pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
 	}
 
 	/* Process options */
-	if (r->max_mss && pf_normalize_tcpopt(r, m, th, off))
+	if (r->max_mss && pf_normalize_tcpopt(r, m, th, off, pd->af))
 		rewrite = 1;
 
 	/* copy back packet headers if we sanitized */
 	if (rewrite)
+#ifdef __FreeBSD__
 		m_copyback(m, off, sizeof(*th), (caddr_t)th);
+#else
+		m_copyback(m, off, sizeof(*th), th);
+#endif
 
 	return (PF_PASS);
 
@@ -1506,11 +1700,13 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
 #ifdef __FreeBSD__
 	KASSERT((src->scrub == NULL), 
 	    ("pf_normalize_tcp_init: src->scrub != NULL"));
+
+	src->scrub = pool_get(&V_pf_state_scrub_pl, PR_NOWAIT);
 #else
 	KASSERT(src->scrub == NULL);
-#endif
 
 	src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
+#endif
 	if (src->scrub == NULL)
 		return (1);
 	bzero(src->scrub, sizeof(*src->scrub));
@@ -1586,10 +1782,17 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
 void
 pf_normalize_tcp_cleanup(struct pf_state *state)
 {
+#ifdef __FreeBSD__
+	if (state->src.scrub)
+		pool_put(&V_pf_state_scrub_pl, state->src.scrub);
+	if (state->dst.scrub)
+		pool_put(&V_pf_state_scrub_pl, state->dst.scrub);
+#else
 	if (state->src.scrub)
 		pool_put(&pf_state_scrub_pl, state->src.scrub);
 	if (state->dst.scrub)
 		pool_put(&pf_state_scrub_pl, state->dst.scrub);
+#endif
 
 	/* Someday... flush the TCP segment reassembly descriptors. */
 }
@@ -1667,7 +1870,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 
 				if (got_ts) {
 					/* Huh?  Multiple timestamps!? */
+#ifdef __FreeBSD__
+					if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 					if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 						DPFPRINTF(("multiple TS??"));
 						pf_print_state(state);
 						printf("\n");
@@ -1736,7 +1943,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 	if (src->scrub && (src->scrub->pfss_flags & PFSS_PAWS) &&
 	    (uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
 	    time_second - state->creation > TS_MAX_CONN))  {
+#ifdef __FreeBSD__
+		if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 		if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 			DPFPRINTF(("src idled out of PAWS\n"));
 			pf_print_state(state);
 			printf("\n");
@@ -1746,7 +1957,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 	}
 	if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) &&
 	    uptime.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) {
+#ifdef __FreeBSD__
+		if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 		if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 			DPFPRINTF(("dst idled out of PAWS\n"));
 			pf_print_state(state);
 			printf("\n");
@@ -1807,7 +2022,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 		 *    network conditions that re-order packets and
 		 *    cause our view of them to decrease.  For now the
 		 *    only lowerbound we can safely determine is that
-		 *    the TS echo will never be less than the orginal
+		 *    the TS echo will never be less than the original
 		 *    TS.  XXX There is probably a better lowerbound.
 		 *    Remove TS_MAX_CONN with better lowerbound check.
 		 *        tescr >= other original TS
@@ -1830,7 +2045,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 		 * this packet.
 		 */
 		if ((ts_fudge = state->rule.ptr->timeout[PFTM_TS_DIFF]) == 0)
+#ifdef __FreeBSD__
+			ts_fudge = V_pf_default_rule.timeout[PFTM_TS_DIFF];
+#else
 			ts_fudge = pf_default_rule.timeout[PFTM_TS_DIFF];
+#endif
 
 
 		/* Calculate max ticks since the last timestamp */
@@ -1838,7 +2057,7 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 #define TS_MICROSECS	1000000		/* microseconds per second */
 #ifdef __FreeBSD__
 #ifndef timersub
-#define timersub(tvp, uvp, vvp)						\
+#define	timersub(tvp, uvp, vvp)						\
 	do {								\
 		(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
 		(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;	\
@@ -1895,7 +2114,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 			    "\n", dst->scrub->pfss_tsval,
 			    dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0));
 #endif
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 			if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 				pf_print_state(state);
 				pf_print_flags(th->th_flags);
 				printf("\n");
@@ -1943,7 +2166,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 			 * Hey!  Someone tried to sneak a packet in.  Or the
 			 * stack changed its RFC1323 behavior?!?!
 			 */
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+#else
 			if (pf_status.debug >= PF_DEBUG_MISC) {
+#endif
 				DPFPRINTF(("Did not receive expected RFC1323 "
 				    "timestamp\n"));
 				pf_print_state(state);
@@ -1970,7 +2197,11 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 			src->scrub->pfss_flags |= PFSS_DATA_TS;
 		else {
 			src->scrub->pfss_flags |= PFSS_DATA_NOTS;
+#ifdef __FreeBSD__
+			if (V_pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
+#else
 			if (pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
+#endif
 			    (dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
 				/* Don't warn if other host rejected RFC1323 */
 				DPFPRINTF(("Broken RFC1323 stack did not "
@@ -2018,17 +2249,25 @@ pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
 
 int
 pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
-    int off)
+    int off, sa_family_t af)
 {
 	u_int16_t	*mss;
 	int		 thoff;
 	int		 opt, cnt, optlen = 0;
 	int		 rewrite = 0;
-	u_char		*optp;
+#ifdef __FreeBSD__
+	u_char		 opts[TCP_MAXOLEN];
+#else
+	u_char		 opts[MAX_TCPOPTLEN];
+#endif
+	u_char		*optp = opts;
 
 	thoff = th->th_off << 2;
 	cnt = thoff - sizeof(struct tcphdr);
-	optp = mtod(m, caddr_t) + off + sizeof(struct tcphdr);
+
+	if (cnt > 0 && !pf_pull_hdr(m, off + sizeof(*th), opts, cnt,
+	    NULL, NULL, af))
+		return (rewrite);
 
 	for (; cnt > 0; cnt -= optlen, optp += optlen) {
 		opt = optp[0];
@@ -2058,5 +2297,63 @@ pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
 		}
 	}
 
+	if (rewrite)
+		m_copyback(m, off + sizeof(*th), thoff - sizeof(*th), opts);
+
 	return (rewrite);
 }
+
+void
+pf_scrub_ip(struct mbuf **m0, u_int32_t flags, u_int8_t min_ttl, u_int8_t tos)
+{
+	struct mbuf		*m = *m0;
+	struct ip		*h = mtod(m, struct ip *);
+
+	/* Clear IP_DF if no-df was requested */
+	if (flags & PFRULE_NODF && h->ip_off & htons(IP_DF)) {
+		u_int16_t ip_off = h->ip_off;
+
+		h->ip_off &= htons(~IP_DF);
+		h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
+	}
+
+	/* Enforce a minimum ttl, may cause endless packet loops */
+	if (min_ttl && h->ip_ttl < min_ttl) {
+		u_int16_t ip_ttl = h->ip_ttl;
+
+		h->ip_ttl = min_ttl;
+		h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
+	}
+
+	/* Enforce tos */
+	if (flags & PFRULE_SET_TOS) {
+		u_int16_t	ov, nv;
+
+		ov = *(u_int16_t *)h;
+		h->ip_tos = tos;
+		nv = *(u_int16_t *)h;
+
+		h->ip_sum = pf_cksum_fixup(h->ip_sum, ov, nv, 0);
+	}
+
+	/* random-id, but not for fragments */
+	if (flags & PFRULE_RANDOMID && !(h->ip_off & ~htons(IP_DF))) {
+		u_int16_t ip_id = h->ip_id;
+
+		h->ip_id = ip_randomid();
+		h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0);
+	}
+}
+
+#ifdef INET6
+void
+pf_scrub_ip6(struct mbuf **m0, u_int8_t min_ttl)
+{
+	struct mbuf		*m = *m0;
+	struct ip6_hdr		*h = mtod(m, struct ip6_hdr *);
+
+	/* Enforce a minimum ttl, may cause endless packet loops */
+	if (min_ttl && h->ip6_hlim < min_ttl)
+		h->ip6_hlim = min_ttl;
+}
+#endif
diff --git a/sys/contrib/pf/net/pf_osfp.c b/sys/contrib/pf/net/pf_osfp.c
index 225528d..dcd8af7 100644
--- a/sys/contrib/pf/net/pf_osfp.c
+++ b/sys/contrib/pf/net/pf_osfp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf_osfp.c,v 1.12 2006/12/13 18:14:10 itojun Exp $ */
+/*	$OpenBSD: pf_osfp.c,v 1.14 2008/06/12 18:17:01 henning Exp $ */
 
 /*
  * Copyright (c) 2003 Mike Frantzen 
@@ -25,7 +25,10 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #ifdef _KERNEL
-# include 
+#include 
+#ifndef __FreeBSD__
+#include 
+#endif
 #endif /* _KERNEL */
 #include 
 
@@ -42,10 +45,17 @@ __FBSDID("$FreeBSD$");
 #include 
 #endif
 
+
 #ifdef _KERNEL
-# define DPFPRINTF(format, x...)		\
+#ifdef __FreeBSD__
+#define	DPFPRINTF(format, x...)		\
+	if (V_pf_status.debug >= PF_DEBUG_NOISY)	\
+		printf(format , ##x)
+#else
+#define	DPFPRINTF(format, x...)		\
 	if (pf_status.debug >= PF_DEBUG_NOISY)	\
 		printf(format , ##x)
+#endif
 #ifdef __FreeBSD__
 typedef uma_zone_t pool_t;
 #else
@@ -55,33 +65,43 @@ typedef struct pool pool_t;
 #else
 /* Userland equivalents so we can lend code to tcpdump et al. */
 
-# include 
-# include 
-# include 
-# include 
-# include 
-# include 
-# define pool_t			int
-# define pool_get(pool, flags)	malloc(*(pool))
-# define pool_put(pool, item)	free(item)
-# define pool_init(pool, size, a, ao, f, m, p)	(*(pool)) = (size)
-
-# ifdef __FreeBSD__
-# define NTOHS(x) (x) = ntohs((u_int16_t)(x))
-# endif
-
-# ifdef PFDEBUG
-#  include 
-#  define DPFPRINTF(format, x...)	fprintf(stderr, format , ##x)
-# else
-#  define DPFPRINTF(format, x...)	((void)0)
-# endif /* PFDEBUG */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#define	pool_t			int
+#define	pool_get(pool, flags)	malloc(*(pool))
+#define	pool_put(pool, item)	free(item)
+#define	pool_init(pool, size, a, ao, f, m, p)	(*(pool)) = (size)
+
+#ifdef __FreeBSD__
+#define	NTOHS(x) (x) = ntohs((u_int16_t)(x))
+#endif
+
+#ifdef PFDEBUG
+#include 
+#define	DPFPRINTF(format, x...)	fprintf(stderr, format , ##x)
+#else
+#define	DPFPRINTF(format, x...)	((void)0)
+#endif /* PFDEBUG */
 #endif /* _KERNEL */
 
 
+#ifdef __FreeBSD__
+SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
+VNET_DEFINE(struct pf_osfp_list,	pf_osfp_list);
+#define	V_pf_osfp_list			VNET(pf_osfp_list)
+VNET_DEFINE(pool_t,			pf_osfp_entry_pl);
+#define	pf_osfp_entry_pl		VNET(pf_osfp_entry_pl)
+VNET_DEFINE(pool_t,			pf_osfp_pl);
+#define	pf_osfp_pl			VNET(pf_osfp_pl)
+#else
 SLIST_HEAD(pf_osfp_list, pf_os_fingerprint) pf_osfp_list;
 pool_t pf_osfp_entry_pl;
 pool_t pf_osfp_pl;
+#endif
 
 struct pf_os_fingerprint	*pf_osfp_find(struct pf_osfp_list *,
 				    struct pf_os_fingerprint *, u_int8_t);
@@ -264,7 +284,11 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st
 	    (fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
 	    fp.fp_wscale);
 
+#ifdef __FreeBSD__
+	if ((fpresult = pf_osfp_find(&V_pf_osfp_list, &fp,
+#else
 	if ((fpresult = pf_osfp_find(&pf_osfp_list, &fp,
+#endif
 	    PF_OSFP_MAXTTL_OFFSET)))
 		return (&fpresult->fp_oses);
 	return (NULL);
@@ -310,20 +334,23 @@ pf_osfp_initialize(void)
 {
 #if defined(__FreeBSD__) && defined(_KERNEL)
 	int error = ENOMEM;
-	
+
 	do {
 		pf_osfp_entry_pl = pf_osfp_pl = NULL;
 		UMA_CREATE(pf_osfp_entry_pl, struct pf_osfp_entry, "pfospfen");
 		UMA_CREATE(pf_osfp_pl, struct pf_os_fingerprint, "pfosfp");
 		error = 0;
 	} while(0);
+
+	SLIST_INIT(&V_pf_osfp_list);
 #else
 	pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
 	    "pfosfpen", &pool_allocator_nointr);
 	pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
 	    "pfosfp", &pool_allocator_nointr);
-#endif
 	SLIST_INIT(&pf_osfp_list);
+#endif
+
 #ifdef __FreeBSD__
 #ifdef _KERNEL
 	return (error);
@@ -337,6 +364,7 @@ pf_osfp_initialize(void)
 void
 pf_osfp_cleanup(void)
 {
+
 	UMA_DESTROY(pf_osfp_entry_pl);
 	UMA_DESTROY(pf_osfp_pl);
 }
@@ -349,8 +377,13 @@ pf_osfp_flush(void)
 	struct pf_os_fingerprint *fp;
 	struct pf_osfp_entry *entry;
 
+#ifdef __FreeBSD__
+	while ((fp = SLIST_FIRST(&V_pf_osfp_list))) {
+		SLIST_REMOVE_HEAD(&V_pf_osfp_list, fp_next);
+#else
 	while ((fp = SLIST_FIRST(&pf_osfp_list))) {
 		SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
+#endif
 		while ((entry = SLIST_FIRST(&fp->fp_oses))) {
 			SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
 			pool_put(&pf_osfp_entry_pl, entry);
@@ -377,6 +410,7 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
 	fpadd.fp_wscale = fpioc->fp_wscale;
 	fpadd.fp_ttl = fpioc->fp_ttl;
 
+#if 0	/* XXX RYAN wants to fix logging */
 	DPFPRINTF("adding osfp %s %s %s = %s%d:%d:%d:%s%d:0x%llx %d "
 	    "(TS=%s,M=%s%d,W=%s%d) %x\n",
 	    fpioc->fp_os.fp_class_nm, fpioc->fp_os.fp_version_nm,
@@ -400,17 +434,31 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
 	    (fpadd.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
 	    fpadd.fp_wscale,
 	    fpioc->fp_os.fp_os);
+#endif
 
-
+#ifdef __FreeBSD__
+	if ((fp = pf_osfp_find_exact(&V_pf_osfp_list, &fpadd))) {
+#else
 	if ((fp = pf_osfp_find_exact(&pf_osfp_list, &fpadd))) {
+#endif
 		 SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
 			if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
 				return (EEXIST);
 		}
-		if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL)
+		if ((entry = pool_get(&pf_osfp_entry_pl,
+#ifdef __FreeBSD__
+		    PR_NOWAIT)) == NULL)
+#else
+		    PR_WAITOK|PR_LIMITFAIL)) == NULL)
+#endif
 			return (ENOMEM);
 	} else {
-		if ((fp = pool_get(&pf_osfp_pl, PR_NOWAIT)) == NULL)
+		if ((fp = pool_get(&pf_osfp_pl,
+#ifdef __FreeBSD__
+		    PR_NOWAIT)) == NULL)
+#else
+		    PR_WAITOK|PR_LIMITFAIL)) == NULL)
+#endif
 			return (ENOMEM);
 		memset(fp, 0, sizeof(*fp));
 		fp->fp_tcpopts = fpioc->fp_tcpopts;
@@ -422,11 +470,20 @@ pf_osfp_add(struct pf_osfp_ioctl *fpioc)
 		fp->fp_wscale = fpioc->fp_wscale;
 		fp->fp_ttl = fpioc->fp_ttl;
 		SLIST_INIT(&fp->fp_oses);
-		if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL) {
+		if ((entry = pool_get(&pf_osfp_entry_pl,
+#ifdef __FreeBSD__
+		    PR_NOWAIT)) == NULL) {
+#else
+		    PR_WAITOK|PR_LIMITFAIL)) == NULL) {
+#endif
 			pool_put(&pf_osfp_pl, fp);
 			return (ENOMEM);
 		}
+#ifdef __FreeBSD__
+		pf_osfp_insert(&V_pf_osfp_list, fp);
+#else
 		pf_osfp_insert(&pf_osfp_list, fp);
+#endif
 	}
 	memcpy(entry, &fpioc->fp_os, sizeof(*entry));
 
@@ -452,7 +509,7 @@ pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
 {
 	struct pf_os_fingerprint *f;
 
-#define MATCH_INT(_MOD, _DC, _field)					\
+#define	MATCH_INT(_MOD, _DC, _field)					\
 	if ((f->fp_flags & _DC) == 0) {					\
 		if ((f->fp_flags & _MOD) == 0) {			\
 			if (f->_field != find->_field)			\
@@ -480,10 +537,11 @@ pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
 				if (find->fp_mss == 0)
 					continue;
 
-/* Some "smart" NAT devices and DSL routers will tweak the MSS size and
+/*
+ * Some "smart" NAT devices and DSL routers will tweak the MSS size and
  * will set it to whatever is suitable for the link type.
  */
-#define SMART_MSS	1460
+#define	SMART_MSS	1460
 				if ((find->fp_wsize % find->fp_mss ||
 				    find->fp_wsize / find->fp_mss !=
 				    f->fp_wsize) &&
@@ -495,8 +553,8 @@ pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
 				if (find->fp_mss == 0)
 					continue;
 
-#define MTUOFF	(sizeof(struct ip) + sizeof(struct tcphdr))
-#define SMART_MTU	(SMART_MSS + MTUOFF)
+#define	MTUOFF		(sizeof(struct ip) + sizeof(struct tcphdr))
+#define	SMART_MTU	(SMART_MSS + MTUOFF)
 				if ((find->fp_wsize % (find->fp_mss + MTUOFF) ||
 				    find->fp_wsize / (find->fp_mss + MTUOFF) !=
 				    f->fp_wsize) &&
@@ -567,7 +625,11 @@ pf_osfp_get(struct pf_osfp_ioctl *fpioc)
 
 
 	memset(fpioc, 0, sizeof(*fpioc));
+#ifdef __FreeBSD__
+	SLIST_FOREACH(fp, &V_pf_osfp_list, fp_next) {
+#else
 	SLIST_FOREACH(fp, &pf_osfp_list, fp_next) {
+#endif
 		SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
 			if (i++ == num) {
 				fpioc->fp_mss = fp->fp_mss;
@@ -594,7 +656,11 @@ pf_osfp_validate(void)
 {
 	struct pf_os_fingerprint *f, *f2, find;
 
+#ifdef __FreeBSD__
+	SLIST_FOREACH(f, &V_pf_osfp_list, fp_next) {
+#else
 	SLIST_FOREACH(f, &pf_osfp_list, fp_next) {
+#endif
 		memcpy(&find, f, sizeof(find));
 
 		/* We do a few MSS/th_win percolations to make things unique */
@@ -606,7 +672,11 @@ pf_osfp_validate(void)
 			find.fp_wsize *= (find.fp_mss + 40);
 		else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
 			find.fp_wsize *= 2;
+#ifdef __FreeBSD__
+		if (f != (f2 = pf_osfp_find(&V_pf_osfp_list, &find, 0))) {
+#else
 		if (f != (f2 = pf_osfp_find(&pf_osfp_list, &find, 0))) {
+#endif
 			if (f2)
 				printf("Found \"%s %s %s\" instead of "
 				    "\"%s %s %s\"\n",
diff --git a/sys/contrib/pf/net/pf_ruleset.c b/sys/contrib/pf/net/pf_ruleset.c
index 7ff6a77..ca8667c 100644
--- a/sys/contrib/pf/net/pf_ruleset.c
+++ b/sys/contrib/pf/net/pf_ruleset.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf_ruleset.c,v 1.1 2006/10/27 13:56:51 mcbride Exp $ */
+/*	$OpenBSD: pf_ruleset.c,v 1.2 2008/12/18 15:31:37 dhill Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -61,48 +61,55 @@ __FBSDID("$FreeBSD$");
 
 
 #ifdef _KERNEL
-# define DPFPRINTF(format, x...)		\
-	if (pf_status.debug >= PF_DEBUG_NOISY)	\
+#ifdef __FreeBSD__
+#define DPFPRINTF(format, x...)				\
+	if (V_pf_status.debug >= PF_DEBUG_NOISY)	\
+		printf(format , ##x)
+#else
+#define DPFPRINTF(format, x...)				\
+	if (pf_status.debug >= PF_DEBUG_NOISY)		\
 		printf(format , ##x)
+#endif
 #ifdef __FreeBSD__
-#define rs_malloc(x)		malloc(x, M_TEMP, M_NOWAIT)
+#define rs_malloc(x)		malloc(x, M_TEMP, M_NOWAIT|M_ZERO)
 #else
-#define rs_malloc(x)		malloc(x, M_TEMP, M_WAITOK)
+#define rs_malloc(x)		malloc(x, M_TEMP, M_WAITOK|M_CANFAIL|M_ZERO)
 #endif
 #define rs_free(x)		free(x, M_TEMP)
 
 #else
 /* Userland equivalents so we can lend code to pfctl et al. */
 
-# include 
-# include 
-# include 
-# include 
-# include 
-# define rs_malloc(x)		 malloc(x)
-# define rs_free(x)		 free(x)
-
-# ifdef PFDEBUG
-#  include 
-#  define DPFPRINTF(format, x...)	fprintf(stderr, format , ##x)
-# else
-#  define DPFPRINTF(format, x...)	((void)0)
-# endif /* PFDEBUG */
+#include 
+#include 
+#include 
+#include 
+#include 
+#define rs_malloc(x)		 calloc(1, x)
+#define rs_free(x)		 free(x)
+
+#ifdef PFDEBUG
+#include 
+#define DPFPRINTF(format, x...)	fprintf(stderr, format , ##x)
+#else
+#define DPFPRINTF(format, x...)	((void)0)
+#endif /* PFDEBUG */
 #endif /* _KERNEL */
 
+#if defined(__FreeBSD__) && !defined(_KERNEL)
+#undef V_pf_anchors
+#define V_pf_anchors		 pf_anchors
+
+#undef pf_main_ruleset
+#define pf_main_ruleset		 pf_main_anchor.ruleset
+#endif
 
+#if defined(__FreeBSD__) && defined(_KERNEL)
+VNET_DEFINE(struct pf_anchor_global,	pf_anchors);
+VNET_DEFINE(struct pf_anchor,		pf_main_anchor);
+#else
 struct pf_anchor_global	 pf_anchors;
 struct pf_anchor	 pf_main_anchor;
-
-#ifndef __FreeBSD__
-/* XXX: hum? */
-int			 pf_get_ruleset_number(u_int8_t);
-void			 pf_init_ruleset(struct pf_ruleset *);
-int			 pf_anchor_setup(struct pf_rule *,
-			    const struct pf_ruleset *, const char *);
-int			 pf_anchor_copyout(const struct pf_ruleset *,
-			    const struct pf_rule *, struct pfioc_rule *);
-void			 pf_anchor_remove(struct pf_rule *);
 #endif
 
 static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
@@ -168,9 +175,14 @@ pf_find_anchor(const char *path)
 	struct pf_anchor	*key, *found;
 
 	key = (struct pf_anchor *)rs_malloc(sizeof(*key));
-	memset(key, 0, sizeof(*key));
+	if (key == NULL)
+		return (NULL);
 	strlcpy(key->path, path, sizeof(key->path));
+#ifdef __FreeBSD__
+	found = RB_FIND(pf_anchor_global, &V_pf_anchors, key);
+#else
 	found = RB_FIND(pf_anchor_global, &pf_anchors, key);
+#endif
 	rs_free(key);
 	return (found);
 }
@@ -210,7 +222,8 @@ pf_find_or_create_ruleset(const char *path)
 	if (ruleset != NULL)
 		return (ruleset);
 	p = (char *)rs_malloc(MAXPATHLEN);
-	bzero(p, MAXPATHLEN);
+	if (p == NULL)
+		return (NULL);
 	strlcpy(p, path, MAXPATHLEN);
 	while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
 		*q = 0;
@@ -242,7 +255,6 @@ pf_find_or_create_ruleset(const char *path)
 			rs_free(p);
 			return (NULL);
 		}
-		memset(anchor, 0, sizeof(*anchor));
 		RB_INIT(&anchor->children);
 		strlcpy(anchor->name, q, sizeof(anchor->name));
 		if (parent != NULL) {
@@ -251,7 +263,11 @@ pf_find_or_create_ruleset(const char *path)
 			strlcat(anchor->path, "/", sizeof(anchor->path));
 		}
 		strlcat(anchor->path, anchor->name, sizeof(anchor->path));
+#ifdef __FreeBSD__
+		if ((dup = RB_INSERT(pf_anchor_global, &V_pf_anchors, anchor)) !=
+#else
 		if ((dup = RB_INSERT(pf_anchor_global, &pf_anchors, anchor)) !=
+#endif
 		    NULL) {
 			printf("pf_find_or_create_ruleset: RB_INSERT1 "
 			    "'%s' '%s' collides with '%s' '%s'\n",
@@ -268,7 +284,11 @@ pf_find_or_create_ruleset(const char *path)
 				    "RB_INSERT2 '%s' '%s' collides with "
 				    "'%s' '%s'\n", anchor->path, anchor->name,
 				    dup->path, dup->name);
+#ifdef __FreeBSD__
+				RB_REMOVE(pf_anchor_global, &V_pf_anchors,
+#else
 				RB_REMOVE(pf_anchor_global, &pf_anchors,
+#endif
 				    anchor);
 				rs_free(anchor);
 				rs_free(p);
@@ -304,7 +324,11 @@ pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
 			    !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
 			    ruleset->rules[i].inactive.open)
 				return;
+#ifdef __FreeBSD__
+		RB_REMOVE(pf_anchor_global, &V_pf_anchors, ruleset->anchor);
+#else
 		RB_REMOVE(pf_anchor_global, &pf_anchors, ruleset->anchor);
+#endif
 		if ((parent = ruleset->anchor->parent) != NULL)
 			RB_REMOVE(pf_anchor_node, &parent->children,
 			    ruleset->anchor);
@@ -328,7 +352,8 @@ pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
 	if (!name[0])
 		return (0);
 	path = (char *)rs_malloc(MAXPATHLEN);
-	bzero(path, MAXPATHLEN);
+	if (path == NULL)
+		return (1);
 	if (name[0] == '/')
 		strlcpy(path, name + 1, MAXPATHLEN);
 	else {
@@ -386,7 +411,8 @@ pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r,
 		int	 i;
 
 		a = (char *)rs_malloc(MAXPATHLEN);
-		bzero(a, MAXPATHLEN);
+		if (a == NULL)
+			return (1);
 		if (rs->anchor == NULL)
 			a[0] = 0;
 		else
diff --git a/sys/contrib/pf/net/pf_subr.c b/sys/contrib/pf/net/pf_subr.c
deleted file mode 100644
index 07f5295..0000000
--- a/sys/contrib/pf/net/pf_subr.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
- *	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.
- * 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.
- *
- */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include 
-__FBSDID("$FreeBSD$");
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-/*
- * Following is where TCP initial sequence number generation occurs.
- *
- * There are two places where we must use initial sequence numbers:
- * 1.  In SYN-ACK packets.
- * 2.  In SYN packets.
- *
- * All ISNs for SYN-ACK packets are generated by the syncache.  See
- * tcp_syncache.c for details.
- *
- * The ISNs in SYN packets must be monotonic; TIME_WAIT recycling
- * depends on this property.  In addition, these ISNs should be
- * unguessable so as to prevent connection hijacking.  To satisfy
- * the requirements of this situation, the algorithm outlined in
- * RFC 1948 is used, with only small modifications.
- *
- * Implementation details:
- *
- * Time is based off the system timer, and is corrected so that it
- * increases by one megabyte per second.  This allows for proper
- * recycling on high speed LANs while still leaving over an hour
- * before rollover.
- *
- * As reading the *exact* system time is too expensive to be done
- * whenever setting up a TCP connection, we increment the time
- * offset in two ways.  First, a small random positive increment
- * is added to isn_offset for each connection that is set up.
- * Second, the function tcp_isn_tick fires once per clock tick
- * and increments isn_offset as necessary so that sequence numbers
- * are incremented at approximately ISN_BYTES_PER_SECOND.  The
- * random positive increments serve only to ensure that the same
- * exact sequence number is never sent out twice (as could otherwise
- * happen when a port is recycled in less than the system tick
- * interval.)
- *
- * net.inet.tcp.isn_reseed_interval controls the number of seconds
- * between seeding of isn_secret.  This is normally set to zero,
- * as reseeding should not be necessary.
- *
- * Locking of the global variables isn_secret, isn_last_reseed, isn_offset,
- * isn_offset_old, and isn_ctx is performed using the TCP pcbinfo lock.  In
- * general, this means holding an exclusive (write) lock.
- */
-
-#define ISN_BYTES_PER_SECOND 1048576
-#define ISN_STATIC_INCREMENT 4096
-#define ISN_RANDOM_INCREMENT (4096 - 1)
-
-static u_char pf_isn_secret[32];
-static int pf_isn_last_reseed;
-static u_int32_t pf_isn_offset;
-
-u_int32_t
-pf_new_isn(struct pf_state *s)
-{
-	MD5_CTX isn_ctx;
-	u_int32_t md5_buffer[4];
-	u_int32_t new_isn;
-	struct pf_state_host *src, *dst;
-
-	/* Seed if this is the first use, reseed if requested. */
-	if (pf_isn_last_reseed == 0) {
-		read_random(&pf_isn_secret, sizeof(pf_isn_secret));
-		pf_isn_last_reseed = ticks;
-	}
-
-	if (s->direction == PF_IN) {
-		src = &s->ext;
-		dst = &s->gwy;
-	} else {
-		src = &s->lan;
-		dst = &s->ext;
-	}
-
-	/* Compute the md5 hash and return the ISN. */
-	MD5Init(&isn_ctx);
-	MD5Update(&isn_ctx, (u_char *) &dst->port, sizeof(u_short));
-	MD5Update(&isn_ctx, (u_char *) &src->port, sizeof(u_short));
-#ifdef INET6
-	if (s->af == AF_INET6) {
-		MD5Update(&isn_ctx, (u_char *) &dst->addr,
-			  sizeof(struct in6_addr));
-		MD5Update(&isn_ctx, (u_char *) &src->addr,
-			  sizeof(struct in6_addr));
-	} else
-#endif
-	{
-		MD5Update(&isn_ctx, (u_char *) &dst->addr,
-			  sizeof(struct in_addr));
-		MD5Update(&isn_ctx, (u_char *) &src->addr,
-			  sizeof(struct in_addr));
-	}
-	MD5Update(&isn_ctx, (u_char *) &pf_isn_secret, sizeof(pf_isn_secret));
-	MD5Final((u_char *) &md5_buffer, &isn_ctx);
-	new_isn = (tcp_seq) md5_buffer[0];
-	pf_isn_offset += ISN_STATIC_INCREMENT +
-		(arc4random() & ISN_RANDOM_INCREMENT);
-	new_isn += pf_isn_offset;
-	return (new_isn);
-}
diff --git a/sys/contrib/pf/net/pf_table.c b/sys/contrib/pf/net/pf_table.c
index 40c9f67..010dc50 100644
--- a/sys/contrib/pf/net/pf_table.c
+++ b/sys/contrib/pf/net/pf_table.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: pf_table.c,v 1.68 2006/05/02 10:08:45 dhartmei Exp $	*/
+/*	$OpenBSD: pf_table.c,v 1.79 2008/10/08 06:24:50 mcbride Exp $	*/
 
 /*
  * Copyright (c) 2002 Cedric Berger
@@ -43,10 +43,10 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 #include 
-#include 
-#include 
 #ifdef __FreeBSD__
 #include 
+#else
+#include 
 #endif
 
 #include 
@@ -55,10 +55,9 @@ __FBSDID("$FreeBSD$");
 #ifndef __FreeBSD__
 #include 
 #endif
-
 #include 
 
-#define ACCEPT_FLAGS(oklist)			\
+#define	ACCEPT_FLAGS(flags, oklist)		\
 	do {					\
 		if ((flags & ~(oklist)) &	\
 		    PFR_FLAG_ALLMASK)		\
@@ -90,28 +89,26 @@ _copyout(const void *uaddr, void *kaddr, size_t len)
 	return (r);
 }
 
-#define COPYIN(from, to, size)			\
+#define	COPYIN(from, to, size, flags)		\
 	((flags & PFR_FLAG_USERIOCTL) ?		\
 	_copyin((from), (to), (size)) :		\
 	(bcopy((from), (to), (size)), 0))
 
-#define COPYOUT(from, to, size)			\
+#define	COPYOUT(from, to, size, flags)		\
 	((flags & PFR_FLAG_USERIOCTL) ?		\
 	_copyout((from), (to), (size)) :	\
 	(bcopy((from), (to), (size)), 0))
 
 #else
-
-#define COPYIN(from, to, size)			\
+#define	COPYIN(from, to, size, flags)		\
 	((flags & PFR_FLAG_USERIOCTL) ?		\
 	copyin((from), (to), (size)) :		\
 	(bcopy((from), (to), (size)), 0))
 
-#define COPYOUT(from, to, size)			\
+#define	COPYOUT(from, to, size, flags)		\
 	((flags & PFR_FLAG_USERIOCTL) ?		\
 	copyout((from), (to), (size)) :		\
 	(bcopy((from), (to), (size)), 0))
-
 #endif
 
 #define	FILLIN_SIN(sin, addr)			\
@@ -128,26 +125,26 @@ _copyout(const void *uaddr, void *kaddr, size_t len)
 		(sin6).sin6_addr = (addr);	\
 	} while (0)
 
-#define SWAP(type, a1, a2)			\
+#define	SWAP(type, a1, a2)			\
 	do {					\
 		type tmp = a1;			\
 		a1 = a2;			\
 		a2 = tmp;			\
 	} while (0)
 
-#define SUNION2PF(su, af) (((af)==AF_INET) ?	\
+#define	SUNION2PF(su, af) (((af)==AF_INET) ?	\
     (struct pf_addr *)&(su)->sin.sin_addr :	\
     (struct pf_addr *)&(su)->sin6.sin6_addr)
 
 #define	AF_BITS(af)		(((af)==AF_INET)?32:128)
 #define	ADDR_NETWORK(ad)	((ad)->pfra_net < AF_BITS((ad)->pfra_af))
 #define	KENTRY_NETWORK(ke)	((ke)->pfrke_net < AF_BITS((ke)->pfrke_af))
-#define KENTRY_RNF_ROOT(ke) \
+#define	KENTRY_RNF_ROOT(ke) \
 		((((struct radix_node *)(ke))->rn_flags & RNF_ROOT) != 0)
 
-#define NO_ADDRESSES		(-1)
-#define ENQUEUE_UNMARKED_ONLY	(1)
-#define INVERT_NEG_FLAG		(1)
+#define	NO_ADDRESSES		(-1)
+#define	ENQUEUE_UNMARKED_ONLY	(1)
+#define	INVERT_NEG_FLAG		(1)
 
 struct pfr_walktree {
 	enum pfrw_op {
@@ -169,28 +166,37 @@ struct pfr_walktree {
 	int	 pfrw_free;
 	int	 pfrw_flags;
 };
-#define pfrw_addr	pfrw_1.pfrw1_addr
-#define pfrw_astats	pfrw_1.pfrw1_astats
-#define pfrw_workq	pfrw_1.pfrw1_workq
-#define pfrw_kentry	pfrw_1.pfrw1_kentry
-#define pfrw_dyn	pfrw_1.pfrw1_dyn
-#define pfrw_cnt	pfrw_free
+#define	pfrw_addr	pfrw_1.pfrw1_addr
+#define	pfrw_astats	pfrw_1.pfrw1_astats
+#define	pfrw_workq	pfrw_1.pfrw1_workq
+#define	pfrw_kentry	pfrw_1.pfrw1_kentry
+#define	pfrw_dyn	pfrw_1.pfrw1_dyn
+#define	pfrw_cnt	pfrw_free
 
-#define senderr(e)	do { rv = (e); goto _bad; } while (0)
+#define	senderr(e)	do { rv = (e); goto _bad; } while (0)
 
 #ifdef __FreeBSD__
-uma_zone_t		 pfr_ktable_pl;
-uma_zone_t		 pfr_kentry_pl;
-uma_zone_t		 pfr_kentry_pl2;
+VNET_DEFINE(uma_zone_t,			pfr_ktable_pl);
+VNET_DEFINE(uma_zone_t,			pfr_kentry_pl);
+VNET_DEFINE(uma_zone_t,			pfr_kcounters_pl);
+#define	V_pfr_kcounters_pl		VNET(pfr_kcounters_pl)
+VNET_DEFINE(struct sockaddr_in,		pfr_sin);
+#define	V_pfr_sin			VNET(pfr_sin)
+VNET_DEFINE(struct sockaddr_in6,	pfr_sin6);
+#define	V_pfr_sin6			VNET(pfr_sin6)
+VNET_DEFINE(union sockaddr_union,	pfr_mask);
+#define	V_pfr_mask			VNET(pfr_mask)
+VNET_DEFINE(struct pf_addr,		pfr_ffaddr);
+#define	V_pfr_ffaddr			VNET(pfr_ffaddr)
 #else
 struct pool		 pfr_ktable_pl;
 struct pool		 pfr_kentry_pl;
-struct pool		 pfr_kentry_pl2;
-#endif
+struct pool		 pfr_kcounters_pl;
 struct sockaddr_in	 pfr_sin;
 struct sockaddr_in6	 pfr_sin6;
 union sockaddr_union	 pfr_mask;
 struct pf_addr		 pfr_ffaddr;
+#endif
 
 void			 pfr_copyout_addr(struct pfr_addr *,
 			    struct pfr_kentry *ke);
@@ -226,7 +232,7 @@ void			 pfr_setflags_ktable(struct pfr_ktable *, int);
 void			 pfr_clstats_ktables(struct pfr_ktableworkq *, long,
 			    int);
 void			 pfr_clstats_ktable(struct pfr_ktable *, long, int);
-struct pfr_ktable	*pfr_create_ktable(struct pfr_table *, long, int);
+struct pfr_ktable	*pfr_create_ktable(struct pfr_table *, long, int, int);
 void			 pfr_destroy_ktables(struct pfr_ktableworkq *, int);
 void			 pfr_destroy_ktable(struct pfr_ktable *, int);
 int			 pfr_ktable_compare(struct pfr_ktable *,
@@ -251,12 +257,11 @@ pfr_initialize(void)
 {
 #ifndef __FreeBSD__
 	pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0,
-	    "pfrktable", &pool_allocator_oldnointr);
+	    "pfrktable", NULL);
 	pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
-	    "pfrkentry", &pool_allocator_oldnointr);
-	pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0,
-	    "pfrkentry2", NULL);
-#endif
+	    "pfrkentry", NULL);
+	pool_init(&pfr_kcounters_pl, sizeof(struct pfr_kcounters), 0, 0, 0,
+	    "pfrkcounters", NULL);
 
 	pfr_sin.sin_len = sizeof(pfr_sin);
 	pfr_sin.sin_family = AF_INET;
@@ -264,6 +269,14 @@ pfr_initialize(void)
 	pfr_sin6.sin6_family = AF_INET6;
 
 	memset(&pfr_ffaddr, 0xff, sizeof(pfr_ffaddr));
+#else
+	V_pfr_sin.sin_len = sizeof(V_pfr_sin);
+	V_pfr_sin.sin_family = AF_INET;
+	V_pfr_sin6.sin6_len = sizeof(V_pfr_sin6);
+	V_pfr_sin6.sin6_family = AF_INET6;
+
+	memset(&V_pfr_ffaddr, 0xff, sizeof(V_pfr_ffaddr));
+#endif
 }
 
 int
@@ -273,7 +286,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
 	struct pfr_kentryworkq	 workq;
 	int			 s;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
 	if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -284,7 +297,6 @@ pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
 	pfr_enqueue_addrs(kt, &workq, ndel, 0);
 
 	if (!(flags & PFR_FLAG_DUMMY)) {
-		s = 0;
 		if (flags & PFR_FLAG_ATOMIC)
 			s = splsoftnet();
 		pfr_remove_kentries(kt, &workq);
@@ -307,10 +319,11 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	struct pfr_kentryworkq	 workq;
 	struct pfr_kentry	*p, *q;
 	struct pfr_addr		 ad;
-	int			 i, rv, s = 0, xadd = 0;
+	int			 i, rv, s, xadd = 0;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
+	    PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -318,12 +331,13 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 		return (ESRCH);
 	if (kt->pfrkt_flags & PFR_TFLAG_CONST)
 		return (EPERM);
-	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
+	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0,
+	    !(flags & PFR_FLAG_USERIOCTL));
 	if (tmpkt == NULL)
 		return (ENOMEM);
 	SLIST_INIT(&workq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad)))
+		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 			senderr(EFAULT);
 		if (pfr_validate_addr(&ad))
 			senderr(EINVAL);
@@ -340,7 +354,8 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 				ad.pfra_fback = PFR_FB_NONE;
 		}
 		if (p == NULL && q == NULL) {
-			p = pfr_create_kentry(&ad, 0);
+			p = pfr_create_kentry(&ad,
+			    !(flags & PFR_FLAG_USERIOCTL));
 			if (p == NULL)
 				senderr(ENOMEM);
 			if (pfr_route_kentry(tmpkt, p)) {
@@ -351,10 +366,9 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 				xadd++;
 			}
 		}
-		if (flags & PFR_FLAG_FEEDBACK) {
-			if (COPYOUT(&ad, addr+i, sizeof(ad)))
+		if (flags & PFR_FLAG_FEEDBACK)
+			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
 				senderr(EFAULT);
-		}
 	}
 	pfr_clean_node_mask(tmpkt, &workq);
 	if (!(flags & PFR_FLAG_DUMMY)) {
@@ -386,9 +400,10 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	struct pfr_kentryworkq	 workq;
 	struct pfr_kentry	*p;
 	struct pfr_addr		 ad;
-	int			 i, rv, s = 0, xdel = 0, log = 1;
+	int			 i, rv, s, xdel = 0, log = 1;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
+	    PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -415,7 +430,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	} else {
 		/* iterate over addresses to delete */
 		for (i = 0; i < size; i++) {
-			if (COPYIN(addr+i, &ad, sizeof(ad)))
+			if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 				return (EFAULT);
 			if (pfr_validate_addr(&ad))
 				return (EINVAL);
@@ -426,7 +441,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	}
 	SLIST_INIT(&workq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad)))
+		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 			senderr(EFAULT);
 		if (pfr_validate_addr(&ad))
 			senderr(EINVAL);
@@ -448,7 +463,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 			xdel++;
 		}
 		if (flags & PFR_FLAG_FEEDBACK)
-			if (COPYOUT(&ad, addr+i, sizeof(ad)))
+			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
 				senderr(EFAULT);
 	}
 	if (!(flags & PFR_FLAG_DUMMY)) {
@@ -476,10 +491,11 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	struct pfr_kentryworkq	 addq, delq, changeq;
 	struct pfr_kentry	*p, *q;
 	struct pfr_addr		 ad;
-	int			 i, rv, s = 0, xadd = 0, xdel = 0, xchange = 0;
+	int			 i, rv, s, xadd = 0, xdel = 0, xchange = 0;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
+	    PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, ignore_pfrt_flags, flags &
 	    PFR_FLAG_USERIOCTL))
 		return (EINVAL);
@@ -488,7 +504,8 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 		return (ESRCH);
 	if (kt->pfrkt_flags & PFR_TFLAG_CONST)
 		return (EPERM);
-	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
+	tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0,
+	    !(flags & PFR_FLAG_USERIOCTL));
 	if (tmpkt == NULL)
 		return (ENOMEM);
 	pfr_mark_addrs(kt);
@@ -496,7 +513,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	SLIST_INIT(&delq);
 	SLIST_INIT(&changeq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad)))
+		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 			senderr(EFAULT);
 		if (pfr_validate_addr(&ad))
 			senderr(EINVAL);
@@ -519,7 +536,8 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 				ad.pfra_fback = PFR_FB_DUPLICATE;
 				goto _skip;
 			}
-			p = pfr_create_kentry(&ad, 0);
+			p = pfr_create_kentry(&ad,
+			    !(flags & PFR_FLAG_USERIOCTL));
 			if (p == NULL)
 				senderr(ENOMEM);
 			if (pfr_route_kentry(tmpkt, p)) {
@@ -533,7 +551,7 @@ pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 		}
 _skip:
 		if (flags & PFR_FLAG_FEEDBACK)
-			if (COPYOUT(&ad, addr+i, sizeof(ad)))
+			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
 				senderr(EFAULT);
 	}
 	pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
@@ -546,7 +564,7 @@ _skip:
 		SLIST_FOREACH(p, &delq, pfrke_workq) {
 			pfr_copyout_addr(&ad, p);
 			ad.pfra_fback = PFR_FB_DELETED;
-			if (COPYOUT(&ad, addr+size+i, sizeof(ad)))
+			if (COPYOUT(&ad, addr+size+i, sizeof(ad), flags))
 				senderr(EFAULT);
 			i++;
 		}
@@ -590,7 +608,7 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	struct pfr_addr		 ad;
 	int			 i, xmatch = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_REPLACE);
+	ACCEPT_FLAGS(flags, PFR_FLAG_REPLACE);
 	if (pfr_validate_table(tbl, 0, 0))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -598,7 +616,7 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 		return (ESRCH);
 
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad)))
+		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 			return (EFAULT);
 		if (pfr_validate_addr(&ad))
 			return (EINVAL);
@@ -611,7 +629,7 @@ pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 		    (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
 		if (p != NULL && !p->pfrke_not)
 			xmatch++;
-		if (COPYOUT(&ad, addr+i, sizeof(ad)))
+		if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
 			return (EFAULT);
 	}
 	if (nmatch != NULL)
@@ -627,7 +645,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
 	struct pfr_walktree	 w;
 	int			 rv;
 
-	ACCEPT_FLAGS(0);
+	ACCEPT_FLAGS(flags, 0);
 	if (pfr_validate_table(tbl, 0, 0))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -650,7 +668,7 @@ pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
 #endif
 	if (!rv)
 #ifdef __FreeBSD__
-		rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, 
+		rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
 		    &w);
 #else
 		rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
@@ -674,10 +692,11 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
 	struct pfr_ktable	*kt;
 	struct pfr_walktree	 w;
 	struct pfr_kentryworkq	 workq;
-	int			 rv, s = 0;
+	int			 rv, s;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
+	/* XXX PFR_FLAG_CLSTATS disabled */
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC);
 	if (pfr_validate_table(tbl, 0, 0))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -733,9 +752,10 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	struct pfr_kentryworkq	 workq;
 	struct pfr_kentry	*p;
 	struct pfr_addr		 ad;
-	int			 i, rv, s = 0, xzero = 0;
+	int			 i, rv, s, xzero = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
+	    PFR_FLAG_FEEDBACK);
 	if (pfr_validate_table(tbl, 0, 0))
 		return (EINVAL);
 	kt = pfr_lookup_table(tbl);
@@ -743,7 +763,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 		return (ESRCH);
 	SLIST_INIT(&workq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad)))
+		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 			senderr(EFAULT);
 		if (pfr_validate_addr(&ad))
 			senderr(EINVAL);
@@ -751,7 +771,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 		if (flags & PFR_FLAG_FEEDBACK) {
 			ad.pfra_fback = (p != NULL) ?
 			    PFR_FB_CLEARED : PFR_FB_NONE;
-			if (COPYOUT(&ad, addr+i, sizeof(ad)))
+			if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
 				senderr(EFAULT);
 		}
 		if (p != NULL) {
@@ -866,7 +886,11 @@ struct pfr_kentry *
 pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
 {
 	union sockaddr_union	 sa, mask;
-	struct radix_node_head	*head = NULL;	/* make the compiler happy */
+#ifdef __FreeBSD__
+	struct radix_node_head	*head = NULL;
+#else
+	struct radix_node_head	*head;
+#endif
 	struct pfr_kentry	*ke;
 	int			 s;
 
@@ -904,12 +928,19 @@ pfr_create_kentry(struct pfr_addr *ad, int intr)
 	struct pfr_kentry	*ke;
 
 	if (intr)
-		ke = pool_get(&pfr_kentry_pl2, PR_NOWAIT);
+#ifdef __FreeBSD__
+		ke = pool_get(&V_pfr_kentry_pl, PR_NOWAIT | PR_ZERO);
+#else
+		ke = pool_get(&pfr_kentry_pl, PR_NOWAIT | PR_ZERO);
+#endif
 	else
-		ke = pool_get(&pfr_kentry_pl, PR_NOWAIT);
+#ifdef __FreeBSD__
+		ke = pool_get(&V_pfr_kentry_pl, PR_WAITOK|PR_ZERO);
+#else
+		ke = pool_get(&pfr_kentry_pl, PR_WAITOK|PR_ZERO|PR_LIMITFAIL);
+#endif
 	if (ke == NULL)
 		return (NULL);
-	bzero(ke, sizeof(*ke));
 
 	if (ad->pfra_af == AF_INET)
 		FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr);
@@ -918,7 +949,6 @@ pfr_create_kentry(struct pfr_addr *ad, int intr)
 	ke->pfrke_af = ad->pfra_af;
 	ke->pfrke_net = ad->pfra_net;
 	ke->pfrke_not = ad->pfra_not;
-	ke->pfrke_intrpool = intr;
 	return (ke);
 }
 
@@ -936,10 +966,14 @@ pfr_destroy_kentries(struct pfr_kentryworkq *workq)
 void
 pfr_destroy_kentry(struct pfr_kentry *ke)
 {
-	if (ke->pfrke_intrpool)
-		pool_put(&pfr_kentry_pl2, ke);
-	else
-		pool_put(&pfr_kentry_pl, ke);
+	if (ke->pfrke_counters)
+#ifdef __FreeBSD__
+		pool_put(&V_pfr_kcounters_pl, ke->pfrke_counters);
+	pool_put(&V_pfr_kentry_pl, ke);
+#else
+		pool_put(&pfr_kcounters_pl, ke->pfrke_counters);
+	pool_put(&pfr_kentry_pl, ke);
+#endif
 }
 
 void
@@ -1020,8 +1054,14 @@ pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange)
 		s = splsoftnet();
 		if (negchange)
 			p->pfrke_not = !p->pfrke_not;
-		bzero(p->pfrke_packets, sizeof(p->pfrke_packets));
-		bzero(p->pfrke_bytes, sizeof(p->pfrke_bytes));
+		if (p->pfrke_counters) {
+#ifdef __FreeBSD__
+			pool_put(&V_pfr_kcounters_pl, p->pfrke_counters);
+#else
+			pool_put(&pfr_kcounters_pl, p->pfrke_counters);
+#endif
+			p->pfrke_counters = NULL;
+		}
 		splx(s);
 		p->pfrke_tzero = tzero;
 	}
@@ -1034,10 +1074,10 @@ pfr_reset_feedback(struct pfr_addr *addr, int size, int flags)
 	int		i;
 
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad)))
+		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 			break;
 		ad.pfra_fback = PFR_FB_NONE;
-		if (COPYOUT(&ad, addr+i, sizeof(ad)))
+		if (COPYOUT(&ad, addr+i, sizeof(ad), flags))
 			break;
 	}
 }
@@ -1072,7 +1112,11 @@ pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
 {
 	union sockaddr_union	 mask;
 	struct radix_node	*rn;
-	struct radix_node_head	*head = NULL;	/* make the compiler happy */
+#ifdef __FreeBSD__
+	struct radix_node_head	*head = NULL;
+#else
+	struct radix_node_head	*head;
+#endif
 	int			 s;
 
 	bzero(ke->pfrke_node, sizeof(ke->pfrke_node));
@@ -1087,9 +1131,17 @@ pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
 #endif
 	if (KENTRY_NETWORK(ke)) {
 		pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
+#ifdef __FreeBSD__
 		rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node);
+#else
+		rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node, 0);
+#endif
 	} else
+#ifdef __FreeBSD__
 		rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node);
+#else
+		rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node, 0);
+#endif
 	splx(s);
 
 	return (rn == NULL ? -1 : 0);
@@ -1100,7 +1152,11 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
 {
 	union sockaddr_union	 mask;
 	struct radix_node	*rn;
-	struct radix_node_head	*head = NULL;	/* make the compiler happy */
+#ifdef __FreeBSD__
+	struct radix_node_head	*head = NULL;
+#else
+	struct radix_node_head	*head;
+#endif
 	int			 s;
 
 	if (ke->pfrke_af == AF_INET)
@@ -1173,7 +1229,7 @@ pfr_walktree(struct radix_node *rn, void *arg)
 			struct pfr_addr ad;
 
 			pfr_copyout_addr(&ad, ke);
-			if (COPYOUT(&ad, w->pfrw_addr, sizeof(ad)))
+			if (copyout(&ad, w->pfrw_addr, sizeof(ad)))
 				return (EFAULT);
 			w->pfrw_addr++;
 		}
@@ -1185,14 +1241,20 @@ pfr_walktree(struct radix_node *rn, void *arg)
 			pfr_copyout_addr(&as.pfras_a, ke);
 
 			s = splsoftnet();
-			bcopy(ke->pfrke_packets, as.pfras_packets,
-			    sizeof(as.pfras_packets));
-			bcopy(ke->pfrke_bytes, as.pfras_bytes,
-			    sizeof(as.pfras_bytes));
+			if (ke->pfrke_counters) {
+				bcopy(ke->pfrke_counters->pfrkc_packets,
+				    as.pfras_packets, sizeof(as.pfras_packets));
+				bcopy(ke->pfrke_counters->pfrkc_bytes,
+				    as.pfras_bytes, sizeof(as.pfras_bytes));
+			} else {
+				bzero(as.pfras_packets, sizeof(as.pfras_packets));
+				bzero(as.pfras_bytes, sizeof(as.pfras_bytes));
+				as.pfras_a.pfra_fback = PFR_FB_NOCOUNT;
+			}
 			splx(s);
 			as.pfras_tzero = ke->pfrke_tzero;
 
-			if (COPYOUT(&as, w->pfrw_astats, sizeof(as)))
+			if (COPYOUT(&as, w->pfrw_astats, sizeof(as), flags))
 				return (EFAULT);
 			w->pfrw_astats++;
 		}
@@ -1209,19 +1271,35 @@ pfr_walktree(struct radix_node *rn, void *arg)
 		if (ke->pfrke_af == AF_INET) {
 			if (w->pfrw_dyn->pfid_acnt4++ > 0)
 				break;
+#ifdef __FreeBSD__
+			pfr_prepare_network(&V_pfr_mask, AF_INET, ke->pfrke_net);
+#else
 			pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net);
+#endif
 			w->pfrw_dyn->pfid_addr4 = *SUNION2PF(
 			    &ke->pfrke_sa, AF_INET);
 			w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
+#ifdef __FreeBSD__
+			    &V_pfr_mask, AF_INET);
+#else
 			    &pfr_mask, AF_INET);
+#endif
 		} else if (ke->pfrke_af == AF_INET6){
 			if (w->pfrw_dyn->pfid_acnt6++ > 0)
 				break;
+#ifdef __FreeBSD__
+			pfr_prepare_network(&V_pfr_mask, AF_INET6, ke->pfrke_net);
+#else
 			pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
+#endif
 			w->pfrw_dyn->pfid_addr6 = *SUNION2PF(
 			    &ke->pfrke_sa, AF_INET6);
 			w->pfrw_dyn->pfid_mask6 = *SUNION2PF(
+#ifdef __FreeBSD__
+			    &V_pfr_mask, AF_INET6);
+#else
 			    &pfr_mask, AF_INET6);
+#endif
 		}
 		break;
 	}
@@ -1233,9 +1311,10 @@ pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
 {
 	struct pfr_ktableworkq	 workq;
 	struct pfr_ktable	*p;
-	int			 s = 0, xdel = 0;
+	int			 s, xdel = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ALLRSETS);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
+	    PFR_FLAG_ALLRSETS);
 	if (pfr_fix_anchor(filter->pfrt_anchor))
 		return (EINVAL);
 	if (pfr_table_count(filter, flags) < 0)
@@ -1270,14 +1349,14 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
 {
 	struct pfr_ktableworkq	 addq, changeq;
 	struct pfr_ktable	*p, *q, *r, key;
-	int			 i, rv, s = 0, xadd = 0;
+	int			 i, rv, s, xadd = 0;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
 	SLIST_INIT(&addq);
 	SLIST_INIT(&changeq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
 			senderr(EFAULT);
 		if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK,
 		    flags & PFR_FLAG_USERIOCTL))
@@ -1285,7 +1364,8 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
 		key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
 		p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
 		if (p == NULL) {
-			p = pfr_create_ktable(&key.pfrkt_t, tzero, 1);
+			p = pfr_create_ktable(&key.pfrkt_t, tzero, 1,
+			    !(flags & PFR_FLAG_USERIOCTL));
 			if (p == NULL)
 				senderr(ENOMEM);
 			SLIST_FOREACH(q, &addq, pfrkt_workq) {
@@ -1311,7 +1391,8 @@ pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
 				}
 			}
 			key.pfrkt_flags = 0;
-			r = pfr_create_ktable(&key.pfrkt_t, 0, 1);
+			r = pfr_create_ktable(&key.pfrkt_t, 0, 1,
+			    !(flags & PFR_FLAG_USERIOCTL));
 			if (r == NULL)
 				senderr(ENOMEM);
 			SLIST_INSERT_HEAD(&addq, r, pfrkt_workq);
@@ -1350,12 +1431,12 @@ pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
 {
 	struct pfr_ktableworkq	 workq;
 	struct pfr_ktable	*p, *q, key;
-	int			 i, s = 0, xdel = 0;
+	int			 i, s, xdel = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
 	SLIST_INIT(&workq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
 			return (EFAULT);
 		if (pfr_validate_table(&key.pfrkt_t, 0,
 		    flags & PFR_FLAG_USERIOCTL))
@@ -1392,7 +1473,7 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
 	struct pfr_ktable	*p;
 	int			 n, nn;
 
-	ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
 	if (pfr_fix_anchor(filter->pfrt_anchor))
 		return (EINVAL);
 	n = nn = pfr_table_count(filter, flags);
@@ -1407,7 +1488,7 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
 			continue;
 		if (n-- <= 0)
 			continue;
-		if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl)))
+		if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl), flags))
 			return (EFAULT);
 	}
 	if (n) {
@@ -1424,11 +1505,11 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
 {
 	struct pfr_ktable	*p;
 	struct pfr_ktableworkq	 workq;
-	int			 s = 0, n, nn;
+	int			 s, n, nn;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC|PFR_FLAG_ALLRSETS);
-					/* XXX PFR_FLAG_CLSTATS disabled */
+	/* XXX PFR_FLAG_CLSTATS disabled */
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_ALLRSETS);
 	if (pfr_fix_anchor(filter->pfrt_anchor))
 		return (EINVAL);
 	n = nn = pfr_table_count(filter, flags);
@@ -1448,9 +1529,8 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
 			continue;
 		if (!(flags & PFR_FLAG_ATOMIC))
 			s = splsoftnet();
-		if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
-			if (!(flags & PFR_FLAG_ATOMIC))
-				splx(s);
+		if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl), flags)) {
+			splx(s);
 			return (EFAULT);
 		}
 		if (!(flags & PFR_FLAG_ATOMIC))
@@ -1475,13 +1555,14 @@ pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
 {
 	struct pfr_ktableworkq	 workq;
 	struct pfr_ktable	*p, key;
-	int			 i, s = 0, xzero = 0;
+	int			 i, s, xzero = 0;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
+	    PFR_FLAG_ADDRSTOO);
 	SLIST_INIT(&workq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
 			return (EFAULT);
 		if (pfr_validate_table(&key.pfrkt_t, 0, 0))
 			return (EINVAL);
@@ -1509,16 +1590,16 @@ pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
 {
 	struct pfr_ktableworkq	 workq;
 	struct pfr_ktable	*p, *q, key;
-	int			 i, s = 0, xchange = 0, xdel = 0;
+	int			 i, s, xchange = 0, xdel = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
 	if ((setflag & ~PFR_TFLAG_USRMASK) ||
 	    (clrflag & ~PFR_TFLAG_USRMASK) ||
 	    (setflag & clrflag))
 		return (EINVAL);
 	SLIST_INIT(&workq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
 			return (EFAULT);
 		if (pfr_validate_table(&key.pfrkt_t, 0,
 		    flags & PFR_FLAG_USERIOCTL))
@@ -1565,7 +1646,7 @@ pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
 	struct pf_ruleset	*rs;
 	int			 xdel = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
 	rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
 	if (rs == NULL)
 		return (ENOMEM);
@@ -1602,7 +1683,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	struct pf_ruleset	*rs;
 	int			 i, rv, xadd = 0, xaddr = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO);
 	if (size && !(flags & PFR_FLAG_ADDRSTOO))
 		return (EINVAL);
 	if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
@@ -1615,7 +1696,8 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	SLIST_INIT(&tableq);
 	kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
 	if (kt == NULL) {
-		kt = pfr_create_ktable(tbl, 0, 1);
+		kt = pfr_create_ktable(tbl, 0, 1,
+		    !(flags & PFR_FLAG_USERIOCTL));
 		if (kt == NULL)
 			return (ENOMEM);
 		SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq);
@@ -1631,7 +1713,8 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 			kt->pfrkt_root = rt;
 			goto _skip;
 		}
-		rt = pfr_create_ktable(&key.pfrkt_t, 0, 1);
+		rt = pfr_create_ktable(&key.pfrkt_t, 0, 1,
+		    !(flags & PFR_FLAG_USERIOCTL));
 		if (rt == NULL) {
 			pfr_destroy_ktables(&tableq, 0);
 			return (ENOMEM);
@@ -1641,14 +1724,14 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
 	} else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE))
 		xadd++;
 _skip:
-	shadow = pfr_create_ktable(tbl, 0, 0);
+	shadow = pfr_create_ktable(tbl, 0, 0, !(flags & PFR_FLAG_USERIOCTL));
 	if (shadow == NULL) {
 		pfr_destroy_ktables(&tableq, 0);
 		return (ENOMEM);
 	}
 	SLIST_INIT(&addrq);
 	for (i = 0; i < size; i++) {
-		if (COPYIN(addr+i, &ad, sizeof(ad)))
+		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
 			senderr(EFAULT);
 		if (pfr_validate_addr(&ad))
 			senderr(EINVAL);
@@ -1698,7 +1781,7 @@ pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
 	struct pf_ruleset	*rs;
 	int			 xdel = 0;
 
-	ACCEPT_FLAGS(PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
 	rs = pf_find_ruleset(trs->pfrt_anchor);
 	if (rs == NULL || !rs->topen || ticket != rs->tticket)
 		return (0);
@@ -1728,10 +1811,10 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
 	struct pfr_ktable	*p, *q;
 	struct pfr_ktableworkq	 workq;
 	struct pf_ruleset	*rs;
-	int			 s = 0, xadd = 0, xchange = 0;
+	int			 s, xadd = 0, xchange = 0;
 	long			 tzero = time_second;
 
-	ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+	ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
 	rs = pf_find_ruleset(trs->pfrt_anchor);
 	if (rs == NULL || !rs->topen || ticket != rs->tticket)
 		return (EBUSY);
@@ -1992,15 +2075,26 @@ pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse)
 }
 
 struct pfr_ktable *
-pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
+pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset,
+    int intr)
 {
 	struct pfr_ktable	*kt;
 	struct pf_ruleset	*rs;
 
-	kt = pool_get(&pfr_ktable_pl, PR_NOWAIT);
+	if (intr)
+#ifdef __FreeBSD__
+		kt = pool_get(&V_pfr_ktable_pl, PR_NOWAIT|PR_ZERO);
+#else
+		kt = pool_get(&pfr_ktable_pl, PR_NOWAIT|PR_ZERO|PR_LIMITFAIL);
+#endif
+	else
+#ifdef __FreeBSD__
+		kt = pool_get(&V_pfr_ktable_pl, PR_WAITOK|PR_ZERO);
+#else
+		kt = pool_get(&pfr_ktable_pl, PR_WAITOK|PR_ZERO|PR_LIMITFAIL);
+#endif
 	if (kt == NULL)
 		return (NULL);
-	bzero(kt, sizeof(*kt));
 	kt->pfrkt_t = *tbl;
 
 	if (attachruleset) {
@@ -2067,7 +2161,11 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
 		kt->pfrkt_rs->tables--;
 		pf_remove_if_empty_ruleset(kt->pfrkt_rs);
 	}
+#ifdef __FreeBSD__
+	pool_put(&V_pfr_ktable_pl, kt);
+#else
 	pool_put(&pfr_ktable_pl, kt);
+#endif
 }
 
 int
@@ -2102,16 +2200,26 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
 	switch (af) {
 #ifdef INET
 	case AF_INET:
+#ifdef __FreeBSD__
+		V_pfr_sin.sin_addr.s_addr = a->addr32[0];
+		ke = (struct pfr_kentry *)rn_match(&V_pfr_sin, kt->pfrkt_ip4);
+#else
 		pfr_sin.sin_addr.s_addr = a->addr32[0];
 		ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
+#endif
 		if (ke && KENTRY_RNF_ROOT(ke))
 			ke = NULL;
 		break;
 #endif /* INET */
 #ifdef INET6
 	case AF_INET6:
+#ifdef __FreeBSD__
+		bcopy(a, &V_pfr_sin6.sin6_addr, sizeof(V_pfr_sin6.sin6_addr));
+		ke = (struct pfr_kentry *)rn_match(&V_pfr_sin6, kt->pfrkt_ip6);
+#else
 		bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
 		ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
+#endif
 		if (ke && KENTRY_RNF_ROOT(ke))
 			ke = NULL;
 		break;
@@ -2139,16 +2247,26 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
 	switch (af) {
 #ifdef INET
 	case AF_INET:
+#ifdef __FreeBSD__
+		V_pfr_sin.sin_addr.s_addr = a->addr32[0];
+		ke = (struct pfr_kentry *)rn_match(&V_pfr_sin, kt->pfrkt_ip4);
+#else
 		pfr_sin.sin_addr.s_addr = a->addr32[0];
 		ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
+#endif
 		if (ke && KENTRY_RNF_ROOT(ke))
 			ke = NULL;
 		break;
 #endif /* INET */
 #ifdef INET6
 	case AF_INET6:
+#ifdef __FreeBSD__
+		bcopy(a, &V_pfr_sin6.sin6_addr, sizeof(V_pfr_sin6.sin6_addr));
+		ke = (struct pfr_kentry *)rn_match(&V_pfr_sin6, kt->pfrkt_ip6);
+#else
 		bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
 		ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
+#endif
 		if (ke && KENTRY_RNF_ROOT(ke))
 			ke = NULL;
 		break;
@@ -2163,14 +2281,24 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
 	}
 	kt->pfrkt_packets[dir_out][op_pass]++;
 	kt->pfrkt_bytes[dir_out][op_pass] += len;
-	if (ke != NULL && op_pass != PFR_OP_XPASS) {
-		ke->pfrke_packets[dir_out][op_pass]++;
-		ke->pfrke_bytes[dir_out][op_pass] += len;
+	if (ke != NULL && op_pass != PFR_OP_XPASS &&
+	    (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) {
+		if (ke->pfrke_counters == NULL)
+#ifdef __FreeBSD__
+			ke->pfrke_counters = pool_get(&V_pfr_kcounters_pl,
+#else
+			ke->pfrke_counters = pool_get(&pfr_kcounters_pl,
+#endif
+			    PR_NOWAIT | PR_ZERO);
+		if (ke->pfrke_counters != NULL) {
+			ke->pfrke_counters->pfrkc_packets[dir_out][op_pass]++;
+			ke->pfrke_counters->pfrkc_bytes[dir_out][op_pass] += len;
+		}
 	}
 }
 
 struct pfr_ktable *
-pfr_attach_table(struct pf_ruleset *rs, char *name)
+pfr_attach_table(struct pf_ruleset *rs, char *name, int intr)
 {
 	struct pfr_ktable	*kt, *rt;
 	struct pfr_table	 tbl;
@@ -2182,14 +2310,14 @@ pfr_attach_table(struct pf_ruleset *rs, char *name)
 		strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor));
 	kt = pfr_lookup_table(&tbl);
 	if (kt == NULL) {
-		kt = pfr_create_ktable(&tbl, time_second, 1);
+		kt = pfr_create_ktable(&tbl, time_second, 1, intr);
 		if (kt == NULL)
 			return (NULL);
 		if (ac != NULL) {
 			bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
 			rt = pfr_lookup_table(&tbl);
 			if (rt == NULL) {
-				rt = pfr_create_ktable(&tbl, 0, 1);
+				rt = pfr_create_ktable(&tbl, 0, 1, intr);
 				if (rt == NULL) {
 					pfr_destroy_ktable(kt, 0);
 					return (NULL);
@@ -2215,20 +2343,31 @@ pfr_detach_table(struct pfr_ktable *kt)
 		pfr_setflags_ktable(kt, kt->pfrkt_flags&~PFR_TFLAG_REFERENCED);
 }
 
-
 int
 pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
     struct pf_addr **raddr, struct pf_addr **rmask, sa_family_t af)
 {
+#ifdef __FreeBSD__
 	struct pfr_kentry	*ke, *ke2 = NULL;
 	struct pf_addr		*addr = NULL;
+#else
+	struct pfr_kentry	*ke, *ke2;
+	struct pf_addr		*addr;
+#endif
 	union sockaddr_union	 mask;
 	int			 idx = -1, use_counter = 0;
 
+#ifdef __FreeBSD__
+	if (af == AF_INET)
+		addr = (struct pf_addr *)&V_pfr_sin.sin_addr;
+	else if (af == AF_INET6)
+		addr = (struct pf_addr *)&V_pfr_sin6.sin6_addr;
+#else
 	if (af == AF_INET)
 		addr = (struct pf_addr *)&pfr_sin.sin_addr;
 	else if (af == AF_INET6)
 		addr = (struct pf_addr *)&pfr_sin6.sin6_addr;
+#endif
 	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
 		kt = kt->pfrkt_root;
 	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
@@ -2243,11 +2382,21 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
 
 _next_block:
 	ke = pfr_kentry_byidx(kt, idx, af);
-	if (ke == NULL)
+	if (ke == NULL) {
+		kt->pfrkt_nomatch++;
 		return (1);
+	}
+#ifdef __FreeBSD__
+	pfr_prepare_network(&V_pfr_mask, af, ke->pfrke_net);
+#else
 	pfr_prepare_network(&pfr_mask, af, ke->pfrke_net);
+#endif
 	*raddr = SUNION2PF(&ke->pfrke_sa, af);
+#ifdef __FreeBSD__
+	*rmask = SUNION2PF(&V_pfr_mask, af);
+#else
 	*rmask = SUNION2PF(&pfr_mask, af);
+#endif
 
 	if (use_counter) {
 		/* is supplied address within block? */
@@ -2267,27 +2416,42 @@ _next_block:
 		/* this is a single IP address - no possible nested block */
 		PF_ACPY(counter, addr, af);
 		*pidx = idx;
+		kt->pfrkt_match++;
 		return (0);
 	}
 	for (;;) {
 		/* we don't want to use a nested block */
+#ifdef __FreeBSD__
+		if (af == AF_INET)
+			ke2 = (struct pfr_kentry *)rn_match(&V_pfr_sin,
+			    kt->pfrkt_ip4);
+		else if (af == AF_INET6)
+			ke2 = (struct pfr_kentry *)rn_match(&V_pfr_sin6,
+			    kt->pfrkt_ip6);
+#else
 		if (af == AF_INET)
 			ke2 = (struct pfr_kentry *)rn_match(&pfr_sin,
 			    kt->pfrkt_ip4);
 		else if (af == AF_INET6)
 			ke2 = (struct pfr_kentry *)rn_match(&pfr_sin6,
 			    kt->pfrkt_ip6);
+#endif
 		/* no need to check KENTRY_RNF_ROOT() here */
 		if (ke2 == ke) {
 			/* lookup return the same block - perfect */
 			PF_ACPY(counter, addr, af);
 			*pidx = idx;
+			kt->pfrkt_match++;
 			return (0);
 		}
 
 		/* we need to increase the counter past the nested block */
 		pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net);
+#ifdef __FreeBSD__
+		PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &V_pfr_ffaddr, af);
+#else
 		PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af);
+#endif
 		PF_AINC(addr, af);
 		if (!PF_MATCHA(0, *raddr, *rmask, addr, af)) {
 			/* ok, we reached the end of our main block */
diff --git a/sys/contrib/pf/net/pfvar.h b/sys/contrib/pf/net/pfvar.h
index de175b1..2aa4bbf 100644
--- a/sys/contrib/pf/net/pfvar.h
+++ b/sys/contrib/pf/net/pfvar.h
@@ -1,5 +1,4 @@
-/*	$FreeBSD$	*/
-/*	$OpenBSD: pfvar.h,v 1.244 2007/02/23 21:31:51 deraadt Exp $ */
+/*	$OpenBSD: pfvar.h,v 1.282 2009/01/29 15:12:28 pyr Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -78,9 +77,8 @@ struct inpcb;
 #endif
 
 enum	{ PF_INOUT, PF_IN, PF_OUT };
-enum	{ PF_LAN_EXT, PF_EXT_GWY, PF_ID };
 enum	{ PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
-	  PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP };
+	  PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER };
 enum	{ PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
 	  PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX };
 enum	{ PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT,
@@ -90,6 +88,7 @@ enum	{ PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL,
 	  PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER,
 	  PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET };
 enum	{ PF_GET_NONE, PF_GET_CLR_CNTR };
+enum	{ PF_SK_WIRE, PF_SK_STACK, PF_SK_BOTH };
 
 /*
  * Note about PFTM_*: real indices into pf_rule.timeout[] come before
@@ -132,7 +131,8 @@ enum	{ PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS,
 enum	{ PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM,
 	  PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN };
 enum	{ PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
-	  PF_ADDR_TABLE, PF_ADDR_RTLABEL, PF_ADDR_URPFFAILED };
+	  PF_ADDR_TABLE, PF_ADDR_RTLABEL, PF_ADDR_URPFFAILED,
+	  PF_ADDR_RANGE };
 #define PF_POOL_TYPEMASK	0x0f
 #define PF_POOL_STICKYADDR	0x20
 #define	PF_WSCALE_FLAG		0x80
@@ -212,87 +212,106 @@ struct pfi_dynaddr {
  */
 
 #ifdef __FreeBSD__
-#define splsoftnet()	splnet()
+#define	splsoftnet()	splnet()
 
 #define	HTONL(x)	(x) = htonl((__uint32_t)(x))
 #define	HTONS(x)	(x) = htons((__uint16_t)(x))
 #define	NTOHL(x)	(x) = ntohl((__uint32_t)(x))
 #define	NTOHS(x)	(x) = ntohs((__uint16_t)(x))
 
-#define PF_NAME		"pf"
+#define	PF_NAME		"pf"
 
-#define PR_NOWAIT	M_NOWAIT
-#define pool_get(p, f)	uma_zalloc(*(p), (f))
-#define pool_put(p, o)	uma_zfree(*(p), (o))
+#define	PR_NOWAIT	M_NOWAIT
+#define	PR_WAITOK	M_WAIT
+#define	PR_ZERO		M_ZERO
+#define	pool_get(p, f)	uma_zalloc(*(p), (f))
+#define	pool_put(p, o)	uma_zfree(*(p), (o))
 
-#define UMA_CREATE(var, type, desc) \
-		var = uma_zcreate(desc, sizeof(type),	\
-			NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); \
-		if (var == NULL) break
-#define UMA_DESTROY(var) \
-		if(var) uma_zdestroy(var)
+#define	UMA_CREATE(var, type, desc)			\
+	var = uma_zcreate(desc, sizeof(type),		\
+	NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);	\
+	if (var == NULL)				\
+		break
+#define	UMA_DESTROY(var)				\
+	if (var)					\
+		uma_zdestroy(var)
 
+#ifdef __FreeBSD__
+VNET_DECLARE(struct mtx,	 pf_task_mtx);
+#define	V_pf_task_mtx		 VNET(pf_task_mtx)
+
+#define	PF_ASSERT(h)	mtx_assert(&V_pf_task_mtx, (h))
+
+#define	PF_LOCK()	do {				\
+	PF_ASSERT(MA_NOTOWNED);				\
+	mtx_lock(&V_pf_task_mtx);			\
+} while(0)
+#define	PF_UNLOCK()	do {				\
+	PF_ASSERT(MA_OWNED);				\
+	mtx_unlock(&V_pf_task_mtx);			\
+} while(0)
+#else
 extern struct mtx pf_task_mtx;
 
-#define	PF_ASSERT(h) mtx_assert(&pf_task_mtx, (h))
+#define	PF_ASSERT(h)	mtx_assert(&pf_task_mtx, (h))
 
-#define PF_LOCK()	do {			\
-	PF_ASSERT(MA_NOTOWNED);			\
-	mtx_lock(&pf_task_mtx);			\
+#define	PF_LOCK()	do {				\
+	PF_ASSERT(MA_NOTOWNED);				\
+	mtx_lock(&pf_task_mtx);				\
 } while(0)
-#define PF_UNLOCK()	do {			\
-	PF_ASSERT(MA_OWNED);			\
-	mtx_unlock(&pf_task_mtx);		\
+#define	PF_UNLOCK()	do {				\
+	PF_ASSERT(MA_OWNED);				\
+	mtx_unlock(&pf_task_mtx);			\
 } while(0)
+#endif
 
-#define PF_COPYIN(uaddr, kaddr, len, r) do {	\
-	PF_UNLOCK();				\
-	r = copyin((uaddr), (kaddr), (len));	\
-	PF_LOCK();				\
+#define	PF_COPYIN(uaddr, kaddr, len, r)		do {	\
+	PF_UNLOCK();					\
+	r = copyin((uaddr), (kaddr), (len));		\
+	PF_LOCK();					\
 } while(0)
 
-#define PF_COPYOUT(kaddr, uaddr, len, r) do {	\
-	PF_UNLOCK();				\
-	r = copyout((kaddr), (uaddr), (len));	\
-	PF_LOCK();				\
+#define	PF_COPYOUT(kaddr, uaddr, len, r)	do {	\
+	PF_UNLOCK();					\
+	r = copyout((kaddr), (uaddr), (len));		\
+	PF_LOCK();					\
 } while(0)
 
 extern void init_pf_mutex(void);
 extern void destroy_pf_mutex(void);
 
-#define PF_MODVER	1
-#define PFLOG_MODVER	1
-#define PFSYNC_MODVER	1
-
-#define PFLOG_MINVER	1
-#define PFLOG_PREFVER	PFLOG_MODVER
-#define PFLOG_MAXVER	1
-#define PFSYNC_MINVER	1
-#define PFSYNC_PREFVER	PFSYNC_MODVER
-#define PFSYNC_MAXVER	1
-#endif	/* __FreeBSD__ */
-
+#define	PF_MODVER	1
+#define	PFLOG_MODVER	1
+#define	PFSYNC_MODVER	1
+
+#define	PFLOG_MINVER	1
+#define	PFLOG_PREFVER	PFLOG_MODVER
+#define	PFLOG_MAXVER	1
+#define	PFSYNC_MINVER	1
+#define	PFSYNC_PREFVER	PFSYNC_MODVER
+#define	PFSYNC_MAXVER	1
+#endif /* __FreeBSD__ */
 #ifdef INET
 #ifndef INET6
-#define PF_INET_ONLY
+#define	PF_INET_ONLY
 #endif /* ! INET6 */
 #endif /* INET */
 
 #ifdef INET6
 #ifndef INET
-#define PF_INET6_ONLY
+#define	PF_INET6_ONLY
 #endif /* ! INET */
 #endif /* INET6 */
 
 #ifdef INET
 #ifdef INET6
-#define PF_INET_INET6
+#define	PF_INET_INET6
 #endif /* INET6 */
 #endif /* INET */
 
 #else
 
-#define PF_INET_INET6
+#define	PF_INET_INET6
 
 #endif /* _KERNEL */
 
@@ -412,7 +431,10 @@ extern void destroy_pf_mutex(void);
 		((aw)->type == PF_ADDR_TABLE &&				\
 		    !pfr_match_addr((aw)->p.tbl, (x), (af))) ||		\
 		((aw)->type == PF_ADDR_DYNIFTL &&			\
-		    !pfi_match_addr((aw)->p.dyn, (x), (af))) || 	\
+		    !pfi_match_addr((aw)->p.dyn, (x), (af))) ||		\
+		((aw)->type == PF_ADDR_RANGE &&				\
+		    !pf_match_addr_range(&(aw)->v.a.addr,		\
+		    &(aw)->v.a.mask, (x), (af))) ||			\
 		((aw)->type == PF_ADDR_ADDRMASK &&			\
 		    !PF_AZERO(&(aw)->v.a.mask, (af)) &&			\
 		    !PF_MATCHA(0, &(aw)->v.a.addr,			\
@@ -619,12 +641,13 @@ struct pf_rule {
 
 	int			 rtableid;
 	u_int32_t		 timeout[PFTM_MAX];
-	u_int32_t		 states;
+	u_int32_t		 states_cur;
+	u_int32_t		 states_tot;
 	u_int32_t		 max_states;
 	u_int32_t		 src_nodes;
 	u_int32_t		 max_src_nodes;
 	u_int32_t		 max_src_states;
-	u_int32_t		 spare1;		/* netgraph */
+	u_int32_t		 spare1;			/* netgraph */
 	u_int32_t		 max_src_conn;
 	struct {
 		u_int32_t		limit;
@@ -643,7 +666,7 @@ struct pf_rule {
 	u_int16_t		 max_mss;
 	u_int16_t		 tag;
 	u_int16_t		 match_tag;
-	u_int16_t		 spare2;		/* netgraph */
+	u_int16_t		 spare2;			/* netgraph */
 
 	struct pf_rule_uid	 uid;
 	struct pf_rule_gid	 gid;
@@ -673,12 +696,18 @@ struct pf_rule {
 	u_int8_t		 rt;
 	u_int8_t		 return_ttl;
 	u_int8_t		 tos;
+	u_int8_t		 set_tos;
 	u_int8_t		 anchor_relative;
 	u_int8_t		 anchor_wildcard;
 
 #define PF_FLUSH		0x01
 #define PF_FLUSH_GLOBAL		0x02
 	u_int8_t		 flush;
+
+	struct {
+		struct pf_addr		addr;
+		u_int16_t		port;
+	}			divert;
 };
 
 /* rule flags */
@@ -697,10 +726,12 @@ struct pf_rule {
 #define	PFRULE_FRAGDROP		0x0400	/* drop funny fragments */
 #define PFRULE_RANDOMID		0x0800
 #define PFRULE_REASSEMBLE_TCP	0x1000
+#define PFRULE_SET_TOS		0x2000
 
 /* rule flags again */
 #define PFRULE_IFBOUND		0x00010000	/* if-bound */
 #define PFRULE_STATESLOPPY	0x00020000	/* sloppy state tracking */
+#define PFRULE_PFLOW		0x00040000
 
 #define PFSTATE_HIWAT		10000	/* default state table size */
 #define PFSTATE_ADAPT_START	6000	/* default adaptive timeout start */
@@ -758,83 +789,268 @@ struct pf_state_host {
 };
 
 struct pf_state_peer {
+	struct pf_state_scrub	*scrub;	/* state is scrubbed		*/
 	u_int32_t	seqlo;		/* Max sequence number sent	*/
 	u_int32_t	seqhi;		/* Max the other end ACKd + win	*/
 	u_int32_t	seqdiff;	/* Sequence number modulator	*/
 	u_int16_t	max_win;	/* largest window (pre scaling)	*/
+	u_int16_t	mss;		/* Maximum segment size option	*/
 	u_int8_t	state;		/* active state level		*/
 	u_int8_t	wscale;		/* window scaling factor	*/
-	u_int16_t	mss;		/* Maximum segment size option	*/
 	u_int8_t	tcp_est;	/* Did we reach TCPS_ESTABLISHED */
-	struct pf_state_scrub	*scrub;	/* state is scrubbed		*/
-	u_int8_t	pad[3];
+	u_int8_t	pad[1];
 };
 
 TAILQ_HEAD(pf_state_queue, pf_state);
 
-/* keep synced with struct pf_state, used in RB_FIND */
-struct pf_state_cmp {
-	u_int64_t	 id;
-	u_int32_t	 creatorid;
-	struct pf_state_host lan;
-	struct pf_state_host gwy;
-	struct pf_state_host ext;
+/* keep synced with struct pf_state_key, used in RB_FIND */
+struct pf_state_key_cmp {
+	struct pf_addr	 addr[2];
+	u_int16_t	 port[2];
 	sa_family_t	 af;
 	u_int8_t	 proto;
-	u_int8_t	 direction;
-	u_int8_t	 pad;
+	u_int8_t	 pad[2];
+};
+
+struct pf_state_item {
+	TAILQ_ENTRY(pf_state_item)	 entry;
+	struct pf_state			*s;
+};
+
+TAILQ_HEAD(pf_statelisthead, pf_state_item);
+
+struct pf_state_key {
+	struct pf_addr	 addr[2];
+	u_int16_t	 port[2];
+	sa_family_t	 af;
+	u_int8_t	 proto;
+	u_int8_t	 pad[2];
+
+	RB_ENTRY(pf_state_key)	 entry;
+	struct pf_statelisthead	 states;
+	struct pf_state_key	*reverse;
+	struct inpcb		*inp;
+};
+
+/* keep synced with struct pf_state, used in RB_FIND */
+struct pf_state_cmp {
+	u_int64_t		 id;
+	u_int32_t		 creatorid;
+	u_int8_t		 direction;
+	u_int8_t		 pad[3];
 };
 
 struct pf_state {
-	u_int64_t	 id;
+	u_int64_t		 id;
+	u_int32_t		 creatorid;
+	u_int8_t		 direction;
+#ifdef __FreeBSD__
+	u_int8_t		 pad[2];
+	u_int8_t		 local_flags;
+#define	PFSTATE_EXPIRING 0x01
+#else
+	u_int8_t		 pad[3];
+#endif
+
+	TAILQ_ENTRY(pf_state)	 sync_list;
+	TAILQ_ENTRY(pf_state)	 entry_list;
+	RB_ENTRY(pf_state)	 entry_id;
+	struct pf_state_peer	 src;
+	struct pf_state_peer	 dst;
+	union pf_rule_ptr	 rule;
+	union pf_rule_ptr	 anchor;
+	union pf_rule_ptr	 nat_rule;
+	struct pf_addr		 rt_addr;
+	struct pf_state_key	*key[2];	/* addresses stack and wire  */
+	struct pfi_kif		*kif;
+	struct pfi_kif		*rt_kif;
+	struct pf_src_node	*src_node;
+	struct pf_src_node	*nat_src_node;
+	u_int64_t		 packets[2];
+	u_int64_t		 bytes[2];
+	u_int32_t		 creation;
+	u_int32_t	 	 expire;
+	u_int32_t		 pfsync_time;
+	u_int16_t		 tag;
+	u_int8_t		 log;
+	u_int8_t		 state_flags;
+#define	PFSTATE_ALLOWOPTS	0x01
+#define	PFSTATE_SLOPPY		0x02
+#define	PFSTATE_PFLOW		0x04
+#define	PFSTATE_NOSYNC		0x08
+#define	PFSTATE_ACK		0x10
+	u_int8_t		 timeout;
+	u_int8_t		 sync_state; /* PFSYNC_S_x */
+
+	/* XXX */
+	u_int8_t		 sync_updates;
+	u_int8_t		_tail[3];
+};
+
+/*
+ * Unified state structures for pulling states out of the kernel
+ * used by pfsync(4) and the pf(4) ioctl.
+ */
+struct pfsync_state_scrub {
+	u_int16_t	pfss_flags;
+	u_int8_t	pfss_ttl;	/* stashed TTL		*/
+#define PFSYNC_SCRUB_FLAG_VALID		0x01
+	u_int8_t	scrub_flag;
+	u_int32_t	pfss_ts_mod;	/* timestamp modulation	*/
+} __packed;
+
+struct pfsync_state_peer {
+	struct pfsync_state_scrub scrub;	/* state is scrubbed	*/
+	u_int32_t	seqlo;		/* Max sequence number sent	*/
+	u_int32_t	seqhi;		/* Max the other end ACKd + win	*/
+	u_int32_t	seqdiff;	/* Sequence number modulator	*/
+	u_int16_t	max_win;	/* largest window (pre scaling)	*/
+	u_int16_t	mss;		/* Maximum segment size option	*/
+	u_int8_t	state;		/* active state level		*/
+	u_int8_t	wscale;		/* window scaling factor	*/
+	u_int8_t	pad[6];
+} __packed;
+
+struct pfsync_state_key {
+	struct pf_addr	 addr[2];
+	u_int16_t	 port[2];
+};
+
+struct pfsync_state {
+	u_int32_t	 id[2];
+	char		 ifname[IFNAMSIZ];
+	struct pfsync_state_key	key[2];
+	struct pfsync_state_peer src;
+	struct pfsync_state_peer dst;
+	struct pf_addr	 rt_addr;
+	u_int32_t	 rule;
+	u_int32_t	 anchor;
+	u_int32_t	 nat_rule;
+	u_int32_t	 creation;
+	u_int32_t	 expire;
+	u_int32_t	 packets[2][2];
+	u_int32_t	 bytes[2][2];
 	u_int32_t	 creatorid;
-	struct pf_state_host lan;
-	struct pf_state_host gwy;
-	struct pf_state_host ext;
 	sa_family_t	 af;
 	u_int8_t	 proto;
 	u_int8_t	 direction;
 #ifdef __FreeBSD__
 	u_int8_t	 local_flags;
-#define	PFSTATE_EXPIRING 0x01
-#else
+#define	PFSTATE_EXPIRING		0x01
 	u_int8_t	 pad;
 #endif
 	u_int8_t	 log;
 	u_int8_t	 state_flags;
-#define	PFSTATE_ALLOWOPTS	0x01
-#define	PFSTATE_SLOPPY		0x02
 	u_int8_t	 timeout;
 	u_int8_t	 sync_flags;
-#define	PFSTATE_NOSYNC	 0x01
-#define	PFSTATE_FROMSYNC 0x02
-#define	PFSTATE_STALE	 0x04
-	union {
-		struct {
-			RB_ENTRY(pf_state)	 entry_lan_ext;
-			RB_ENTRY(pf_state)	 entry_ext_gwy;
-			RB_ENTRY(pf_state)	 entry_id;
-			TAILQ_ENTRY(pf_state)	 entry_list;
-			struct pfi_kif		*kif;
-		} s;
-		char	 ifname[IFNAMSIZ];
-	} u;
-	struct pf_state_peer src;
-	struct pf_state_peer dst;
-	union pf_rule_ptr rule;
-	union pf_rule_ptr anchor;
-	union pf_rule_ptr nat_rule;
-	struct pf_addr	 rt_addr;
-	struct pfi_kif	*rt_kif;
-	struct pf_src_node	*src_node;
-	struct pf_src_node	*nat_src_node;
-	u_int64_t	 packets[2];
-	u_int64_t	 bytes[2];
-	u_int32_t	 creation;
-	u_int32_t	 expire;
-	u_int32_t	 pfsync_time;
-	u_int16_t	 tag;
-};
+	u_int8_t	 updates;
+} __packed;
+
+#ifdef __FreeBSD__
+#ifdef _KERNEL
+/* pfsync */
+typedef int		pfsync_state_import_t(struct pfsync_state *, u_int8_t);
+typedef	void		pfsync_insert_state_t(struct pf_state *);
+typedef	void		pfsync_update_state_t(struct pf_state *);
+typedef	void		pfsync_delete_state_t(struct pf_state *);
+typedef void		pfsync_clear_states_t(u_int32_t, const char *);
+typedef int		pfsync_state_in_use_t(struct pf_state *);
+typedef int		pfsync_defer_t(struct pf_state *, struct mbuf *);
+typedef	int		pfsync_up_t(void);
+
+extern pfsync_state_import_t	*pfsync_state_import_ptr;
+extern pfsync_insert_state_t	*pfsync_insert_state_ptr;
+extern pfsync_update_state_t	*pfsync_update_state_ptr;
+extern pfsync_delete_state_t	*pfsync_delete_state_ptr;
+extern pfsync_clear_states_t	*pfsync_clear_states_ptr;
+extern pfsync_state_in_use_t	*pfsync_state_in_use_ptr;
+extern pfsync_defer_t		*pfsync_defer_ptr;
+extern pfsync_up_t		*pfsync_up_ptr;
+
+void			pfsync_state_export(struct pfsync_state *,
+			    struct pf_state *);
+
+/* pflow */
+typedef int		export_pflow_t(struct pf_state *);
+
+extern export_pflow_t		*export_pflow_ptr;
+
+/* pflog */
+struct pf_ruleset;
+struct pf_pdesc;
+typedef int pflog_packet_t(struct pfi_kif *, struct mbuf *, sa_family_t,
+    u_int8_t, u_int8_t, struct pf_rule *, struct pf_rule *,
+    struct pf_ruleset *, struct pf_pdesc *);
+
+extern pflog_packet_t		*pflog_packet_ptr;
+
+/* pf uid hack */
+VNET_DECLARE(int, debug_pfugidhack);
+#define	V_debug_pfugidhack	VNET(debug_pfugidhack)
+
+#define	V_pf_end_threads	VNET(pf_end_threads)
+#endif
+
+/* Macros to set/clear/test flags. */
+#ifdef _KERNEL
+#define	SET(t, f)	((t) |= (f))
+#define	CLR(t, f)	((t) &= ~(f))
+#define	ISSET(t, f)	((t) & (f))
+#endif
+#endif
+
+#define	PFSYNC_FLAG_SRCNODE	0x04
+#define	PFSYNC_FLAG_NATSRCNODE	0x08
+
+/* for copies to/from network byte order */
+/* ioctl interface also uses network byte order */
+#define pf_state_peer_hton(s,d) do {		\
+	(d)->seqlo = htonl((s)->seqlo);		\
+	(d)->seqhi = htonl((s)->seqhi);		\
+	(d)->seqdiff = htonl((s)->seqdiff);	\
+	(d)->max_win = htons((s)->max_win);	\
+	(d)->mss = htons((s)->mss);		\
+	(d)->state = (s)->state;		\
+	(d)->wscale = (s)->wscale;		\
+	if ((s)->scrub) {						\
+		(d)->scrub.pfss_flags = 				\
+		    htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP);	\
+		(d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl;		\
+		(d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\
+		(d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID;	\
+	}								\
+} while (0)
+
+#define pf_state_peer_ntoh(s,d) do {		\
+	(d)->seqlo = ntohl((s)->seqlo);		\
+	(d)->seqhi = ntohl((s)->seqhi);		\
+	(d)->seqdiff = ntohl((s)->seqdiff);	\
+	(d)->max_win = ntohs((s)->max_win);	\
+	(d)->mss = ntohs((s)->mss);		\
+	(d)->state = (s)->state;		\
+	(d)->wscale = (s)->wscale;		\
+	if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && 	\
+	    (d)->scrub != NULL) {					\
+		(d)->scrub->pfss_flags =				\
+		    ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP;	\
+		(d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl;		\
+		(d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\
+	}								\
+} while (0)
+
+#define pf_state_counter_hton(s,d) do {				\
+	d[0] = htonl((s>>32)&0xffffffff);			\
+	d[1] = htonl(s&0xffffffff);				\
+} while (0)
+
+#define pf_state_counter_from_pfsync(s)				\
+	(((u_int64_t)(s[0])<<32) | (u_int64_t)(s[1]))
+
+#define pf_state_counter_ntoh(s,d) do {				\
+	d = ntohl(s[0]);					\
+	d = d<<32;						\
+	d += ntohl(s[1]);					\
+} while (0)
 
 TAILQ_HEAD(pf_rulequeue, pf_rule);
 
@@ -881,9 +1097,11 @@ RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
 #define PFR_TFLAG_INACTIVE	0x00000008
 #define PFR_TFLAG_REFERENCED	0x00000010
 #define PFR_TFLAG_REFDANCHOR	0x00000020
-#define PFR_TFLAG_USRMASK	0x00000003
+#define PFR_TFLAG_COUNTERS	0x00000040
+/* Adjust masks below when adding flags. */
+#define PFR_TFLAG_USRMASK	0x00000043
 #define PFR_TFLAG_SETMASK	0x0000003C
-#define PFR_TFLAG_ALLMASK	0x0000003F
+#define PFR_TFLAG_ALLMASK	0x0000007F
 
 struct pfr_table {
 	char			 pfrt_anchor[MAXPATHLEN];
@@ -894,7 +1112,7 @@ struct pfr_table {
 
 enum { PFR_FB_NONE, PFR_FB_MATCH, PFR_FB_ADDED, PFR_FB_DELETED,
 	PFR_FB_CHANGED, PFR_FB_CLEARED, PFR_FB_DUPLICATE,
-	PFR_FB_NOTMATCH, PFR_FB_CONFLICT, PFR_FB_MAX };
+	PFR_FB_NOTMATCH, PFR_FB_CONFLICT, PFR_FB_NOCOUNT, PFR_FB_MAX };
 
 struct pfr_addr {
 	union {
@@ -944,20 +1162,32 @@ union sockaddr_union {
 };
 #endif /* _SOCKADDR_UNION_DEFINED */
 
+struct pfr_kcounters {
+	u_int64_t		 pfrkc_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+	u_int64_t		 pfrkc_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+};
+
 SLIST_HEAD(pfr_kentryworkq, pfr_kentry);
 struct pfr_kentry {
 	struct radix_node	 pfrke_node[2];
 	union sockaddr_union	 pfrke_sa;
-	u_int64_t		 pfrke_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
-	u_int64_t		 pfrke_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
 	SLIST_ENTRY(pfr_kentry)	 pfrke_workq;
+	union {
+		
+		struct pfr_kcounters		*pfrke_counters;
+#if 0
+		struct pfr_kroute		*pfrke_route;
+#endif
+	} u;
 	long			 pfrke_tzero;
 	u_int8_t		 pfrke_af;
 	u_int8_t		 pfrke_net;
 	u_int8_t		 pfrke_not;
 	u_int8_t		 pfrke_mark;
-	u_int8_t		 pfrke_intrpool;
 };
+#define pfrke_counters	u.pfrke_counters
+#define pfrke_route	u.pfrke_route
+
 
 SLIST_HEAD(pfr_ktableworkq, pfr_ktable);
 RB_HEAD(pfr_ktablehead, pfr_ktable);
@@ -986,17 +1216,25 @@ struct pfr_ktable {
 #define pfrkt_nomatch	pfrkt_ts.pfrts_nomatch
 #define pfrkt_tzero	pfrkt_ts.pfrts_tzero
 
-RB_HEAD(pf_state_tree_lan_ext, pf_state);
-RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state,
-    u.s.entry_lan_ext, pf_state_compare_lan_ext);
+RB_HEAD(pf_state_tree, pf_state_key);
+RB_PROTOTYPE(pf_state_tree, pf_state_key, entry, pf_state_compare_key);
 
-RB_HEAD(pf_state_tree_ext_gwy, pf_state);
-RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state,
-    u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
+RB_HEAD(pf_state_tree_ext_gwy, pf_state_key);
+RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state_key,
+    entry_ext_gwy, pf_state_compare_ext_gwy);
 
-TAILQ_HEAD(pfi_statehead, pfi_kif);
 RB_HEAD(pfi_ifhead, pfi_kif);
 
+/* state tables */
+#ifdef __FreeBSD__
+#ifdef _KERNEL
+VNET_DECLARE(struct pf_state_tree,	 pf_statetbl);
+#define	V_pf_statetbl			 VNET(pf_statetbl)
+#endif
+#else
+extern struct pf_state_tree	 pf_statetbl;
+#endif
+
 /* keep synced with pfi_kif, used in RB_FIND */
 struct pfi_kif_cmp {
 	char				 pfik_name[IFNAMSIZ];
@@ -1009,12 +1247,7 @@ struct pfi_kif {
 	u_int64_t			 pfik_bytes[2][2][2];
 	u_int32_t			 pfik_tzero;
 	int				 pfik_flags;
-	struct pf_state_tree_lan_ext	 pfik_lan_ext;
-	struct pf_state_tree_ext_gwy	 pfik_ext_gwy;
-	TAILQ_ENTRY(pfi_kif)		 pfik_w_states;
-#ifndef __FreeBSD__
 	void				*pfik_ah_cookie;
-#endif
 	struct ifnet			*pfik_ifp;
 	struct ifg_group		*pfik_group;
 	int				 pfik_states;
@@ -1029,9 +1262,6 @@ enum pfi_kif_refs {
 };
 
 #define PFI_IFLAG_SKIP		0x0100	/* skip filtering on interface */
-/* XXX: revisist */
-#define PFI_IFLAG_SETABLE_MASK	0x0100	/* setable via DIOC{SET,CLR}IFFLAG */
-#define PFI_IFLAG_PLACEHOLDER	0x8000	/* placeholder group/interface */
 
 struct pf_pdesc {
 	struct {
@@ -1050,16 +1280,22 @@ struct pf_pdesc {
 #endif /* INET6 */
 		void			*any;
 	} hdr;
-	struct pf_addr	 baddr;		/* address before translation */
-	struct pf_addr	 naddr;		/* address after translation */
+
 	struct pf_rule	*nat_rule;	/* nat/rdr rule applied to packet */
-	struct pf_addr	*src;
-	struct pf_addr	*dst;
 	struct ether_header
 			*eh;
+	struct pf_addr	*src;		/* src address */
+	struct pf_addr	*dst;		/* dst address */
+	u_int16_t *sport;
+	u_int16_t *dport;
+#ifdef __FreeBSD__
 	struct pf_mtag	*pf_mtag;
-	u_int16_t	*ip_sum;
+#endif
+
 	u_int32_t	 p_len;		/* total length of payload */
+
+	u_int16_t	*ip_sum;
+	u_int16_t	*proto_sum;
 	u_int16_t	 flags;		/* Let SCRUB trigger behavior in
 					 * state code. Easier than tags */
 #define PFDESC_TCP_NORM	0x0001		/* TCP shall be statefully scrubbed */
@@ -1067,6 +1303,9 @@ struct pf_pdesc {
 	sa_family_t	 af;
 	u_int8_t	 proto;
 	u_int8_t	 tos;
+	u_int8_t	 dir;		/* direction */
+	u_int8_t	 sidx;		/* key index for source */
+	u_int8_t	 didx;		/* key index for destination */
 };
 
 /* flags for RDR options */
@@ -1175,6 +1414,15 @@ struct pf_pdesc {
 			*(a) = (x); \
 	} while (0)
 
+#ifdef __FreeBSD__
+#define REASON_SET(a, x) \
+	do { \
+		if ((a) != NULL) \
+			*(a) = (x); \
+		if (x < PFRES_MAX) \
+			V_pf_status.counters[x]++; \
+	} while (0)
+#else
 #define REASON_SET(a, x) \
 	do { \
 		if ((a) != NULL) \
@@ -1182,6 +1430,7 @@ struct pf_pdesc {
 		if (x < PFRES_MAX) \
 			pf_status.counters[x]++; \
 	} while (0)
+#endif
 
 struct pf_status {
 	u_int64_t	counters[PFRES_MAX];
@@ -1265,27 +1514,6 @@ struct pf_altq {
 	u_int32_t		 qid;		/* return value */
 };
 
-#ifndef __FreeBSD__
-
-#define	PF_TAG_GENERATED		0x01
-#define	PF_TAG_FRAGCACHE		0x02
-#define	PF_TAG_TRANSLATE_LOCALHOST	0x04
-
-struct pf_mtag {
-	void		*hdr;		/* saved hdr pos in mbuf, for ECN */
-	u_int		 rtableid;	/* alternate routing table id */
-	u_int32_t	 qid;		/* queue id */
-	u_int16_t	 tag;		/* tag id */
-	u_int8_t	 flags;
-	u_int8_t	 routed;
-	sa_family_t	 af;		/* for ECN */
-};
-#endif
-
-struct pf_tag {
-	u_int16_t	tag;		/* tag id */
-};
-
 struct pf_tagname {
 	TAILQ_ENTRY(pf_tagname)	entries;
 	char			name[PF_TAG_NAME_SIZE];
@@ -1293,6 +1521,14 @@ struct pf_tagname {
 	int			ref;
 };
 
+struct pf_divert {
+	union {
+		struct in_addr	ipv4;
+		struct in6_addr	ipv6;
+	}		addr;
+	u_int16_t	port;
+};
+
 #define PFFRAG_FRENT_HIWAT	5000	/* Number of fragment entries */
 #define PFFRAG_FRAG_HIWAT	1000	/* Number of fragmented packets */
 #define PFFRAG_FRCENT_HIWAT	50000	/* Number of fragment cache entries */
@@ -1343,31 +1579,32 @@ struct pfioc_natlook {
 };
 
 struct pfioc_state {
-	u_int32_t	 nr;
-	struct pf_state	 state;
+	struct pfsync_state	state;
 };
 
 struct pfioc_src_node_kill {
-	/* XXX returns the number of src nodes killed in psnk_af */
 	sa_family_t psnk_af;
 	struct pf_rule_addr psnk_src;
 	struct pf_rule_addr psnk_dst;
+	u_int		    psnk_killed;
 };
 
 struct pfioc_state_kill {
-	/* XXX returns the number of states killed in psk_af */
+	struct pf_state_cmp	psk_pfcmp;
 	sa_family_t		psk_af;
 	int			psk_proto;
 	struct pf_rule_addr	psk_src;
 	struct pf_rule_addr	psk_dst;
 	char			psk_ifname[IFNAMSIZ];
+	char			psk_label[PF_RULE_LABEL_SIZE];
+	u_int			psk_killed;
 };
 
 struct pfioc_states {
 	int	ps_len;
 	union {
-		caddr_t		 psu_buf;
-		struct pf_state	*psu_states;
+		caddr_t			 psu_buf;
+		struct pfsync_state	*psu_states;
 	} ps_u;
 #define ps_buf		ps_u.psu_buf
 #define ps_states	ps_u.psu_states
@@ -1518,55 +1755,97 @@ struct pfioc_iface {
 #define	DIOCRDELTABLES	_IOWR('D', 62, struct pfioc_table)
 #define	DIOCRGETTABLES	_IOWR('D', 63, struct pfioc_table)
 #define	DIOCRGETTSTATS	_IOWR('D', 64, struct pfioc_table)
-#define DIOCRCLRTSTATS  _IOWR('D', 65, struct pfioc_table)
+#define DIOCRCLRTSTATS	_IOWR('D', 65, struct pfioc_table)
 #define	DIOCRCLRADDRS	_IOWR('D', 66, struct pfioc_table)
 #define	DIOCRADDADDRS	_IOWR('D', 67, struct pfioc_table)
 #define	DIOCRDELADDRS	_IOWR('D', 68, struct pfioc_table)
 #define	DIOCRSETADDRS	_IOWR('D', 69, struct pfioc_table)
 #define	DIOCRGETADDRS	_IOWR('D', 70, struct pfioc_table)
 #define	DIOCRGETASTATS	_IOWR('D', 71, struct pfioc_table)
-#define DIOCRCLRASTATS  _IOWR('D', 72, struct pfioc_table)
+#define	DIOCRCLRASTATS	_IOWR('D', 72, struct pfioc_table)
 #define	DIOCRTSTADDRS	_IOWR('D', 73, struct pfioc_table)
 #define	DIOCRSETTFLAGS	_IOWR('D', 74, struct pfioc_table)
-#define DIOCRINADEFINE	_IOWR('D', 77, struct pfioc_table)
-#define DIOCOSFPFLUSH	_IO('D', 78)
-#define DIOCOSFPADD	_IOWR('D', 79, struct pf_osfp_ioctl)
-#define DIOCOSFPGET	_IOWR('D', 80, struct pf_osfp_ioctl)
-#define DIOCXBEGIN      _IOWR('D', 81, struct pfioc_trans)
-#define DIOCXCOMMIT     _IOWR('D', 82, struct pfioc_trans)
-#define DIOCXROLLBACK   _IOWR('D', 83, struct pfioc_trans)
-#define DIOCGETSRCNODES	_IOWR('D', 84, struct pfioc_src_nodes)
-#define DIOCCLRSRCNODES	_IO('D', 85)
-#define DIOCSETHOSTID	_IOWR('D', 86, u_int32_t)
-#define DIOCIGETIFACES	_IOWR('D', 87, struct pfioc_iface)
-#define DIOCSETIFFLAG	_IOWR('D', 89, struct pfioc_iface)
-#define DIOCCLRIFFLAG	_IOWR('D', 90, struct pfioc_iface)
-#define DIOCKILLSRCNODES	_IOWR('D', 91, struct pfioc_src_node_kill)
+#define	DIOCRINADEFINE	_IOWR('D', 77, struct pfioc_table)
+#define	DIOCOSFPFLUSH	_IO('D', 78)
+#define	DIOCOSFPADD	_IOWR('D', 79, struct pf_osfp_ioctl)
+#define	DIOCOSFPGET	_IOWR('D', 80, struct pf_osfp_ioctl)
+#define	DIOCXBEGIN	_IOWR('D', 81, struct pfioc_trans)
+#define	DIOCXCOMMIT	_IOWR('D', 82, struct pfioc_trans)
+#define	DIOCXROLLBACK	_IOWR('D', 83, struct pfioc_trans)
+#define	DIOCGETSRCNODES	_IOWR('D', 84, struct pfioc_src_nodes)
+#define	DIOCCLRSRCNODES	_IO('D', 85)
+#define	DIOCSETHOSTID	_IOWR('D', 86, u_int32_t)
+#define	DIOCIGETIFACES	_IOWR('D', 87, struct pfioc_iface)
+#define	DIOCSETIFFLAG	_IOWR('D', 89, struct pfioc_iface)
+#define	DIOCCLRIFFLAG	_IOWR('D', 90, struct pfioc_iface)
+#define	DIOCKILLSRCNODES	_IOWR('D', 91, struct pfioc_src_node_kill)
 #ifdef __FreeBSD__
 struct pf_ifspeed {
 	char			ifname[IFNAMSIZ];
 	u_int32_t		baudrate;
 };
-#define DIOCGIFSPEED	_IOWR('D', 92, struct pf_ifspeed)
+#define	DIOCGIFSPEED	_IOWR('D', 92, struct pf_ifspeed)
 #endif
 
 #ifdef _KERNEL
 RB_HEAD(pf_src_tree, pf_src_node);
 RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare);
+#ifdef __FreeBSD__
+VNET_DECLARE(struct pf_src_tree,	 tree_src_tracking);
+#define	V_tree_src_tracking		 VNET(tree_src_tracking)
+#else
 extern struct pf_src_tree tree_src_tracking;
+#endif
 
 RB_HEAD(pf_state_tree_id, pf_state);
 RB_PROTOTYPE(pf_state_tree_id, pf_state,
     entry_id, pf_state_compare_id);
+#ifdef __FreeBSD__
+VNET_DECLARE(struct pf_state_tree_id,	 tree_id);
+#define	V_tree_id			 VNET(tree_id)
+VNET_DECLARE(struct pf_state_queue,	 state_list);
+#define	V_state_list			 VNET(state_list)
+#else
 extern struct pf_state_tree_id tree_id;
 extern struct pf_state_queue state_list;
+#endif
 
 TAILQ_HEAD(pf_poolqueue, pf_pool);
+#ifdef __FreeBSD__
+VNET_DECLARE(struct pf_poolqueue,	 pf_pools[2]);
+#define	V_pf_pools			 VNET(pf_pools)
+#else
 extern struct pf_poolqueue		  pf_pools[2];
+#endif
 TAILQ_HEAD(pf_altqqueue, pf_altq);
+#ifdef __FreeBSD__
+VNET_DECLARE(struct pf_altqqueue,	 pf_altqs[2]);
+#define	V_pf_altqs			 VNET(pf_altqs)
+VNET_DECLARE(struct pf_palist,		 pf_pabuf);
+#define	V_pf_pabuf			 VNET(pf_pabuf)
+#else
 extern struct pf_altqqueue		  pf_altqs[2];
 extern struct pf_palist			  pf_pabuf;
+#endif
 
+#ifdef __FreeBSD__
+VNET_DECLARE(u_int32_t,			 ticket_altqs_active);
+#define	V_ticket_altqs_active		 VNET(ticket_altqs_active)
+VNET_DECLARE(u_int32_t,			 ticket_altqs_inactive);
+#define	V_ticket_altqs_inactive		 VNET(ticket_altqs_inactive)
+VNET_DECLARE(int,			 altqs_inactive_open);
+#define	V_altqs_inactive_open		 VNET(altqs_inactive_open)
+VNET_DECLARE(u_int32_t,			 ticket_pabuf);
+#define	V_ticket_pabuf			 VNET(ticket_pabuf)
+VNET_DECLARE(struct pf_altqqueue *,	 pf_altqs_active);
+#define	V_pf_altqs_active		 VNET(pf_altqs_active)
+VNET_DECLARE(struct pf_altqqueue *,	 pf_altqs_inactive);
+#define	V_pf_altqs_inactive		 VNET(pf_altqs_inactive)
+VNET_DECLARE(struct pf_poolqueue *,	 pf_pools_active);
+#define	V_pf_pools_active		 VNET(pf_pools_active)
+VNET_DECLARE(struct pf_poolqueue *,	 pf_pools_inactive);
+#define	V_pf_pools_inactive		 VNET(pf_pools_inactive)
+#else
 extern u_int32_t		 ticket_altqs_active;
 extern u_int32_t		 ticket_altqs_inactive;
 extern int			 altqs_inactive_open;
@@ -1575,6 +1854,7 @@ extern struct pf_altqqueue	*pf_altqs_active;
 extern struct pf_altqqueue	*pf_altqs_inactive;
 extern struct pf_poolqueue	*pf_pools_active;
 extern struct pf_poolqueue	*pf_pools_inactive;
+#endif
 extern int			 pf_tbladdr_setup(struct pf_ruleset *,
 				    struct pf_addr_wrap *);
 extern void			 pf_tbladdr_remove(struct pf_addr_wrap *);
@@ -1582,49 +1862,82 @@ extern void			 pf_tbladdr_copyout(struct pf_addr_wrap *);
 extern void			 pf_calc_skip_steps(struct pf_rulequeue *);
 #ifdef __FreeBSD__
 #ifdef ALTQ
-extern void			 pf_altq_ifnet_event(struct ifnet *, int);
+extern	void			 pf_altq_ifnet_event(struct ifnet *, int);
 #endif
-extern uma_zone_t		 pf_src_tree_pl, pf_rule_pl;
-extern uma_zone_t		 pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
-extern uma_zone_t		 pfr_ktable_pl, pfr_kentry_pl, pfr_kentry_pl2;
-extern uma_zone_t		 pf_cache_pl, pf_cent_pl;
-extern uma_zone_t		 pf_state_scrub_pl;
-extern uma_zone_t		 pfi_addr_pl;
+VNET_DECLARE(uma_zone_t,		 pf_src_tree_pl);
+#define	V_pf_src_tree_pl		 VNET(pf_src_tree_pl)
+VNET_DECLARE(uma_zone_t,		 pf_rule_pl);
+#define	V_pf_rule_pl			 VNET(pf_rule_pl)
+VNET_DECLARE(uma_zone_t,		 pf_state_pl);
+#define	V_pf_state_pl			 VNET(pf_state_pl)
+VNET_DECLARE(uma_zone_t,		 pf_state_key_pl);
+#define	V_pf_state_key_pl		 VNET(pf_state_key_pl)
+VNET_DECLARE(uma_zone_t,		 pf_state_item_pl);
+#define	V_pf_state_item_pl		 VNET(pf_state_item_pl)
+VNET_DECLARE(uma_zone_t,		 pf_altq_pl);
+#define	V_pf_altq_pl			 VNET(pf_altq_pl)
+VNET_DECLARE(uma_zone_t,		 pf_pooladdr_pl);
+#define	V_pf_pooladdr_pl		 VNET(pf_pooladdr_pl)
+VNET_DECLARE(uma_zone_t,		 pfr_ktable_pl);
+#define	V_pfr_ktable_pl			 VNET(pfr_ktable_pl)
+VNET_DECLARE(uma_zone_t,		 pfr_kentry_pl);
+#define	V_pfr_kentry_pl			 VNET(pfr_kentry_pl)
+VNET_DECLARE(uma_zone_t,		 pf_cache_pl);
+#define	V_pf_cache_pl			 VNET(pf_cache_pl)
+VNET_DECLARE(uma_zone_t,		 pf_cent_pl);
+#define	V_pf_cent_pl			 VNET(pf_cent_pl)
+VNET_DECLARE(uma_zone_t,		 pf_state_scrub_pl);
+#define	V_pf_state_scrub_pl		 VNET(pf_state_scrub_pl)
+VNET_DECLARE(uma_zone_t,		 pfi_addr_pl);
+#define	V_pfi_addr_pl			 VNET(pfi_addr_pl)
 #else
 extern struct pool		 pf_src_tree_pl, pf_rule_pl;
-extern struct pool		 pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+extern struct pool		 pf_state_pl, pf_state_key_pl, pf_state_item_pl,
+				    pf_altq_pl, pf_pooladdr_pl;
 extern struct pool		 pf_state_scrub_pl;
 #endif
 extern void			 pf_purge_thread(void *);
 #ifdef __FreeBSD__
 extern int			 pf_purge_expired_src_nodes(int);
-extern int			 pf_purge_expired_states(u_int32_t, int);
+extern int			 pf_purge_expired_states(u_int32_t , int);
 #else
 extern void			 pf_purge_expired_src_nodes(int);
 extern void			 pf_purge_expired_states(u_int32_t);
 #endif
 extern void			 pf_unlink_state(struct pf_state *);
 extern void			 pf_free_state(struct pf_state *);
-extern int			 pf_insert_state(struct pfi_kif *,
+extern int			 pf_state_insert(struct pfi_kif *,
+				    struct pf_state_key *,
+				    struct pf_state_key *,
 				    struct pf_state *);
 extern int			 pf_insert_src_node(struct pf_src_node **,
 				    struct pf_rule *, struct pf_addr *,
 				    sa_family_t);
 void				 pf_src_tree_remove_state(struct pf_state *);
 extern struct pf_state		*pf_find_state_byid(struct pf_state_cmp *);
-extern struct pf_state		*pf_find_state_all(struct pf_state_cmp *key,
-				    u_int8_t tree, int *more);
+extern struct pf_state		*pf_find_state_all(struct pf_state_key_cmp *,
+				    u_int, int *);
 extern void			 pf_print_state(struct pf_state *);
 extern void			 pf_print_flags(u_int8_t);
 extern u_int16_t		 pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
 				    u_int8_t);
 
+#ifdef __FreeBSD__
+VNET_DECLARE(struct ifnet *,		 sync_ifp);
+#define	V_sync_ifp		 	 VNET(sync_ifp);
+VNET_DECLARE(struct pf_rule,		 pf_default_rule);
+#define	V_pf_default_rule		  VNET(pf_default_rule)
+#else
 extern struct ifnet		*sync_ifp;
 extern struct pf_rule		 pf_default_rule;
+#endif
 extern void			 pf_addrcpy(struct pf_addr *, struct pf_addr *,
 				    u_int8_t);
 void				 pf_rm_rule(struct pf_rulequeue *,
 				    struct pf_rule *);
+#ifndef __FreeBSD__
+struct pf_divert		*pf_find_divert(struct mbuf *);
+#endif
 
 #ifdef INET
 #ifdef __FreeBSD__
@@ -1656,8 +1969,11 @@ void	pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t);
 int	pflog_packet(struct pfi_kif *, struct mbuf *, sa_family_t, u_int8_t,
 	    u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *,
 	    struct pf_pdesc *);
+void	pf_send_deferred_syn(struct pf_state *);
 int	pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *,
 	    struct pf_addr *, sa_family_t);
+int	pf_match_addr_range(struct pf_addr *, struct pf_addr *,
+	    struct pf_addr *, sa_family_t);
 int	pf_match(u_int8_t, u_int32_t, u_int32_t, u_int32_t);
 int	pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t);
 int	pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
@@ -1682,10 +1998,13 @@ void	pf_purge_expired_fragments(void);
 int	pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *);
 int	pf_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *);
 #ifdef __FreeBSD__
-int	pf_socket_lookup(int, struct pf_pdesc *, struct inpcb *);
+int	pf_socket_lookup(int, struct pf_pdesc *,  struct inpcb *);
 #else
 int	pf_socket_lookup(int, struct pf_pdesc *);
 #endif
+struct pf_state_key *pf_alloc_state_key(int);
+void	pf_pkt_addr_changed(struct mbuf *);
+int	pf_state_key_attach(struct pf_state_key *, struct pf_state *, int);
 void	pfr_initialize(void);
 int	pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
 void	pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
@@ -1694,7 +2013,7 @@ int	pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *,
 	    struct pf_addr **, struct pf_addr **, sa_family_t);
 void	pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
 struct pfr_ktable *
-	pfr_attach_table(struct pf_ruleset *, char *);
+	pfr_attach_table(struct pf_ruleset *, char *, int);
 void	pfr_detach_table(struct pfr_ktable *);
 int	pfr_clr_tables(struct pfr_table *, int *, int);
 int	pfr_add_tables(struct pfr_table *, int, int *, int);
@@ -1723,8 +2042,12 @@ int	pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int);
 int	pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
 	    int *, u_int32_t, int);
 
-extern struct pfi_statehead	 pfi_statehead;
+#ifdef __FreeBSD__
+VNET_DECLARE(struct pfi_kif *,		 pfi_all);
+#define	V_pfi_all	 		 VNET(pfi_all)
+#else
 extern struct pfi_kif		*pfi_all;
+#endif
 
 void		 pfi_initialize(void);
 #ifdef __FreeBSD__
@@ -1744,30 +2067,44 @@ int		 pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
 int		 pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
 void		 pfi_dynaddr_remove(struct pf_addr_wrap *);
 void		 pfi_dynaddr_copyout(struct pf_addr_wrap *);
-void		 pfi_fill_oldstatus(struct pf_status *);
-int		 pfi_clr_istats(const char *);
+void		 pfi_update_status(const char *, struct pf_status *);
 int		 pfi_get_ifaces(const char *, struct pfi_kif *, int *);
 int		 pfi_set_flags(const char *, int);
 int		 pfi_clear_flags(const char *, int);
 
+#ifdef __FreeBSD__
+int		 pf_match_tag(struct mbuf *, struct pf_rule *, int *,
+		    struct pf_mtag *);
+#else
+int		 pf_match_tag(struct mbuf *, struct pf_rule *, int *);
+#endif
 u_int16_t	 pf_tagname2tag(char *);
 void		 pf_tag2tagname(u_int16_t, char *);
 void		 pf_tag_ref(u_int16_t);
 void		 pf_tag_unref(u_int16_t);
-int		 pf_tag_packet(struct mbuf *, struct pf_mtag *, int, int);
+#ifdef __FreeBSD__
+int		 pf_tag_packet(struct mbuf *, int, int, struct pf_mtag *);
+#else
+int		 pf_tag_packet(struct mbuf *, int, int);
+#endif
 u_int32_t	 pf_qname2qid(char *);
 void		 pf_qid2qname(u_int32_t, char *);
 void		 pf_qid_unref(u_int32_t);
-#ifndef __FreeBSD__
-struct pf_mtag	*pf_find_mtag(struct mbuf *);
-struct pf_mtag	*pf_get_mtag(struct mbuf *);
-#endif
 
+#ifdef __FreeBSD__
+VNET_DECLARE(struct pf_status,		 pf_status);
+#define	V_pf_status			 VNET(pf_status)
+#else
 extern struct pf_status	pf_status;
+#endif
 
 #ifdef __FreeBSD__
-extern uma_zone_t	pf_frent_pl, pf_frag_pl;
-extern struct sx	pf_consistency_lock;
+VNET_DECLARE(uma_zone_t,		 pf_frent_pl);
+#define	V_pf_frent_pl			 VNET(pf_frent_pl)
+VNET_DECLARE(uma_zone_t,		 pf_frag_pl);
+#define	V_pf_frag_pl			 VNET(pf_frag_pl)
+VNET_DECLARE(struct sx,			 pf_consistency_lock);
+#define	V_pf_consistency_lock		 VNET(pf_consistency_lock)
 #else
 extern struct pool	pf_frent_pl, pf_frag_pl;
 extern struct rwlock	pf_consistency_lock;
@@ -1777,7 +2114,12 @@ struct pf_pool_limit {
 	void		*pp;
 	unsigned	 limit;
 };
+#ifdef __FreeBSD__
+VNET_DECLARE(struct pf_pool_limit,		 pf_pool_limits[PF_LIMIT_MAX]);
+#define	V_pf_pool_limits			 VNET(pf_pool_limits)
+#else
 extern struct pf_pool_limit	pf_pool_limits[PF_LIMIT_MAX];
+#endif
 
 #ifdef __FreeBSD__
 struct pf_frent {
@@ -1788,34 +2130,44 @@ struct pf_frent {
 
 struct pf_frcache {
 	LIST_ENTRY(pf_frcache) fr_next;
-	uint16_t        fr_off;
-	uint16_t        fr_end;
+	uint16_t		fr_off;
+	uint16_t		fr_end;
 };
 
 struct pf_fragment {
 	RB_ENTRY(pf_fragment) fr_entry;
 	TAILQ_ENTRY(pf_fragment) frag_next;
-	struct in_addr  fr_src;
-	struct in_addr  fr_dst;
-	u_int8_t        fr_p;           /* protocol of this fragment */
-	u_int8_t        fr_flags;       /* status flags */
-	u_int16_t       fr_id;          /* fragment id for reassemble */
-	u_int16_t       fr_max;         /* fragment data max */
-	u_int32_t       fr_timeout;
-#define fr_queue        fr_u.fru_queue
-#define fr_cache        fr_u.fru_cache
+	struct in_addr	fr_src;
+	struct in_addr	fr_dst;
+	u_int8_t	fr_p;		/* protocol of this fragment */
+	u_int8_t	fr_flags;	/* status flags */
+	u_int16_t	fr_id;		/* fragment id for reassemble */
+	u_int16_t	fr_max;		/* fragment data max */
+	u_int32_t	fr_timeout;
+#define	fr_queue	fr_u.fru_queue
+#define	fr_cache	fr_u.fru_cache
 	union {
-		LIST_HEAD(pf_fragq, pf_frent) fru_queue;        /* buffering */
-		LIST_HEAD(pf_cacheq, pf_frcache) fru_cache;     /* non-buf */
+		LIST_HEAD(pf_fragq, pf_frent) fru_queue;	/* buffering */
+		LIST_HEAD(pf_cacheq, pf_frcache) fru_cache;	/* non-buf */
 	} fr_u;
 };
 #endif /* (__FreeBSD__) */
 
 #endif /* _KERNEL */
 
-extern struct pf_anchor_global  pf_anchors;
-extern struct pf_anchor        pf_main_anchor;
+#ifdef __FreeBSD__
+#ifdef _KERNEL
+VNET_DECLARE(struct pf_anchor_global,		 pf_anchors);
+#define	V_pf_anchors				 VNET(pf_anchors)
+VNET_DECLARE(struct pf_anchor,			 pf_main_anchor);
+#define	V_pf_main_anchor			 VNET(pf_main_anchor)
+#define pf_main_ruleset	V_pf_main_anchor.ruleset
+#endif
+#else
+extern struct pf_anchor_global	pf_anchors;
+extern struct pf_anchor		pf_main_anchor;
 #define pf_main_ruleset	pf_main_anchor.ruleset
+#endif
 
 /* these ruleset functions can be linked into userland programs (pfctl) */
 int			 pf_get_ruleset_number(u_int8_t);
@@ -1832,7 +2184,6 @@ struct pf_ruleset	*pf_find_or_create_ruleset(const char *);
 void			 pf_rs_initialize(void);
 
 #ifndef __FreeBSD__
-/* ?!? */
 #ifdef _KERNEL
 int			 pf_anchor_copyout(const struct pf_ruleset *,
 			    const struct pf_rule *, struct pfioc_rule *);
@@ -1863,4 +2214,31 @@ int	pf_osfp_match(struct pf_osfp_enlist *, pf_osfp_t);
 struct pf_os_fingerprint *
 	pf_osfp_validate(void);
 
+#ifdef _KERNEL
+void			 pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
+
+void			 pf_step_into_anchor(int *, struct pf_ruleset **, int,
+			    struct pf_rule **, struct pf_rule **, int *);
+int			 pf_step_out_of_anchor(int *, struct pf_ruleset **,
+			    int, struct pf_rule **, struct pf_rule **,
+			    int *);
+
+int			 pf_map_addr(u_int8_t, struct pf_rule *,
+			    struct pf_addr *, struct pf_addr *,
+			    struct pf_addr *, struct pf_src_node **);
+struct pf_rule		*pf_get_translation(struct pf_pdesc *, struct mbuf *,
+			    int, int, struct pfi_kif *, struct pf_src_node **,
+			    struct pf_state_key **, struct pf_state_key **,
+			    struct pf_state_key **, struct pf_state_key **,
+			    struct pf_addr *, struct pf_addr *,
+			    u_int16_t, u_int16_t);
+
+int			 pf_state_key_setup(struct pf_pdesc *, struct pf_rule *,
+			    struct pf_state_key **, struct pf_state_key **,
+			    struct pf_state_key **, struct pf_state_key **,
+			    struct pf_addr *, struct pf_addr *,
+			    u_int16_t, u_int16_t);
+#endif /* _KERNEL */
+
+
 #endif /* _NET_PFVAR_H_ */
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 2dbc3d9..ab27a31 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -241,6 +241,7 @@ SUBDIR=	${_3dfx} \
 	pcn \
 	${_pf} \
 	${_pflog} \
+	${_pfsync} \
 	plip \
 	${_pmc} \
 	portalfs \
@@ -382,6 +383,9 @@ _netgraph=	netgraph
 	${MK_INET6_SUPPORT} != "no")) || defined(ALL_MODULES)
 _pf=		pf
 _pflog=		pflog
+.if ${MK_INET_SUPPORT} != "no"
+_pfsync=	pfsync
+.endif
 .endif
 
 .if ${MACHINE_CPUARCH} == "i386"
diff --git a/sys/modules/pf/Makefile b/sys/modules/pf/Makefile
index 78aa564..d4b01da 100644
--- a/sys/modules/pf/Makefile
+++ b/sys/modules/pf/Makefile
@@ -6,16 +6,18 @@
 .PATH: ${.CURDIR}/../../contrib/pf/netinet
 
 KMOD=	pf
-SRCS = 	pf.c pf_if.c pf_subr.c pf_osfp.c pf_ioctl.c pf_norm.c pf_table.c \
+SRCS=	pf.c pf_if.c pf_lb.c pf_osfp.c pf_ioctl.c pf_norm.c pf_table.c \
 	pf_ruleset.c \
 	in4_cksum.c \
-	opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
+	opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h opt_global.h
 
-CFLAGS+=  -I${.CURDIR}/../../contrib/pf
+CFLAGS+= -I${.CURDIR}/../../contrib/pf
 
 .if !defined(KERNBUILDDIR)
+.if ${MK_INET_SUPPORT} != "no"
 opt_inet.h:
 	echo "#define INET 1" > ${.TARGET}
+.endif
 
 .if ${MK_INET6_SUPPORT} != "no"
 opt_inet6.h:
@@ -26,9 +28,17 @@ opt_bpf.h:
 	echo "#define DEV_BPF 1" > ${.TARGET}
 
 # pflog can be loaded as a module, have the additional checks turned on
+# pfsync can be loaded as a module, have the additional checks turned on
 opt_pf.h:
 	echo "#define DEV_PF 1" > ${.TARGET}
 	echo "#define DEV_PFLOG 1" >> ${.TARGET}
+	echo "#define DEV_PFSYNC 1" >> ${.TARGET}
+	echo "#define DEV_PFLOW 1" >> ${.TARGET}
+
+.if defined(VIMAGE)
+opt_global.h:
+	echo "#define VIMAGE 1" >> ${.TARGET}
+.endif
 .endif
 
 .include 
diff --git a/sys/modules/pflog/Makefile b/sys/modules/pflog/Makefile
index 2dbbd6c..0e8339e 100644
--- a/sys/modules/pflog/Makefile
+++ b/sys/modules/pflog/Makefile
@@ -5,14 +5,19 @@
 .PATH: ${.CURDIR}/../../contrib/pf/net
 
 KMOD=	pflog
-SRCS = 	if_pflog.c \
+SRCS=	if_pflog.c \
 	opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
 
-CFLAGS+=  -I${.CURDIR}/../../contrib/pf
+CFLAGS+= -I${.CURDIR}/../../contrib/pf
+SRCS+=	bus_if.h device_if.h
 
-.if !defined(KERNBUILDDIR)
+.if defined(KERNBUILDDIR)
+MKDEP+=		-include ${KERNBUILDDIR}/opt_global.h
+.else
+.if ${MK_INET_SUPPORT} != "no"
 opt_inet.h:
 	echo "#define INET 1" > ${.TARGET}
+.endif
 
 .if ${MK_INET6_SUPPORT} != "no"
 opt_inet6.h:
@@ -21,6 +26,13 @@ opt_inet6.h:
 
 opt_bpf.h:
 	echo "#define DEV_BPF 1" > ${.TARGET}
+
+.if defined(VIMAGE)
+opt_global.h:
+	echo "#define VIMAGE 1" >> ${.TARGET}
+CFLAGS+=	-include opt_global.h
+MKDEP+=		-include opt_global.h
+.endif
 .endif
 
 .include 
diff --git a/sys/modules/pfsync/Makefile b/sys/modules/pfsync/Makefile
new file mode 100644
index 0000000..ad08b45
--- /dev/null
+++ b/sys/modules/pfsync/Makefile
@@ -0,0 +1,38 @@
+# $FreeBSD$
+
+.include 
+
+.PATH: ${.CURDIR}/../../contrib/pf/net
+
+KMOD=	pfsync
+SRCS=	if_pfsync.c \
+	opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
+
+CFLAGS+= -I${.CURDIR}/../../contrib/pf
+SRCS+=	bus_if.h device_if.h
+
+.if defined(KERNBUILDDIR)
+MKDEP+=		-include ${KERNBUILDDIR}/opt_global.h
+.else
+.if ${MK_INET_SUPPORT} != "no"
+opt_inet.h:
+	echo "#define INET 1" > ${.TARGET}
+.endif
+
+.if ${MK_INET6_SUPPORT} != "no"
+opt_inet6.h:
+	echo "#define INET6 1" > ${.TARGET}
+.endif
+
+opt_bpf.h:
+	echo "#define DEV_BPF 1" > ${.TARGET}
+
+.if defined(VIMAGE)
+opt_global.h:
+	echo "#define VIMAGE 1" >> ${.TARGET}
+CFLAGS+=	-include opt_global.h
+MKDEP+=		-include opt_global.h
+.endif
+.endif
+
+.include 
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index 6c60390..22f35df 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -256,6 +256,8 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m)
 #endif
 	}
 
+	m_addr_changed(m);
+
 	error = ip_output(m, NULL, &sc->gif_ro, 0, NULL, NULL);
 
 	if (!(GIF2IFP(sc)->if_flags & IFF_LINK0) &&
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index 3542aa1..ec8a2f0 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -675,6 +675,8 @@ icmp_reflect(struct mbuf *m)
 		goto done;	/* Ip_output() will check for broadcast */
 	}
 
+	m_addr_changed(m);
+
 	t = ip->ip_dst;
 	ip->ip_dst = ip->ip_src;
 
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index 9e5c737..48837a7 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -1670,10 +1670,6 @@ do {								\
 					break;
 				}
 				at->qid = altq->qid;
-				if (is_ipv4)
-					at->af = AF_INET;
-				else
-					at->af = AF_LINK;
 				at->hdr = ip;
 				break;
 			}
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index e754b88..1a8e537 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -100,6 +100,9 @@ void	(*ip_divert_ptr)(struct mbuf *, int);
 int	(*ng_ipfw_input_p)(struct mbuf **, int,
 			struct ip_fw_args *, int);
 
+/* Hook for telling pf that the destination address changed */
+void	(*m_addr_chg_pf_p)(struct mbuf *m);
+
 #ifdef INET
 /*
  * Hooks for multicast routing. They all default to NULL, so leave them not
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 952b38a..6a2da07 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1177,6 +1177,8 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
 		ip6cp.ip6c_src = &icmp6src;
 		ip6cp.ip6c_nxt = nxt;
 
+		m_addr_changed(m);
+
 		if (icmp6type == ICMP6_PACKET_TOO_BIG) {
 			notifymtu = ntohl(icmp6->icmp6_mtu);
 			ip6cp.ip6c_cmdarg = (void *)¬ifymtu;
@@ -2299,6 +2301,8 @@ icmp6_reflect(struct mbuf *m, size_t off)
 
 	m->m_flags &= ~(M_BCAST|M_MCAST);
 
+	m_addr_changed(m);
+
 	ip6_output(m, NULL, NULL, 0, NULL, &outif, NULL);
 	if (outif)
 		icmp6_ifoutstat_inc(outif, type, code);
diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c
index e786836..961fc77 100644
--- a/sys/netinet6/in6_gif.c
+++ b/sys/netinet6/in6_gif.c
@@ -262,6 +262,8 @@ in6_gif_output(struct ifnet *ifp,
 #endif
 	}
 
+	m_addr_changed(m);
+
 #ifdef IPV6_MINMTU
 	/*
 	 * force fragmentation to minimum MTU, to avoid path MTU discovery.
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index a004aef..8b53bf4 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -473,6 +473,8 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
 
 	key_sa_recordxfer(sav, m);		/* record data transfer */
 
+	m_addr_changed(m);
+
 #ifdef DEV_ENC
 	encif->if_ipackets++;
 	encif->if_ibytes += m->m_pkthdr.len;
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index d10523d..77897ed 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -191,6 +191,8 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
 	}
 	key_sa_recordxfer(sav, m);		/* record data transfer */
 
+	m_addr_changed(m);
+
 	/*
 	 * We're done with IPsec processing, transmit the packet using the
 	 * appropriate network protocol (IP or IPv6). SPD lookup will be
diff --git a/sys/netipsec/xform_ipip.c b/sys/netipsec/xform_ipip.c
index 8639c82..0eb8b6a 100644
--- a/sys/netipsec/xform_ipip.c
+++ b/sys/netipsec/xform_ipip.c
@@ -392,6 +392,8 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
 		panic("%s: bogus ip version %u", __func__, v>>4);
 	}
 
+	m_addr_changed(m);
+
 	if (netisr_queue(isr, m)) {	/* (0) on success. */
 		V_ipipstat.ipips_qfull++;
 		DPRINTF(("%s: packet dropped because of full queue\n",
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index c2b7081..b186f79 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -695,6 +695,16 @@ m_last(struct mbuf *m)
 	return (m);
 }
 
+extern void (*m_addr_chg_pf_p)(struct mbuf *m);
+
+static __inline void 
+m_addr_changed(struct mbuf *m)
+{
+
+	if (m_addr_chg_pf_p)
+		m_addr_chg_pf_p(m);
+}
+
 /*
  * mbuf, cluster, and external object allocation macros (for compatibility
  * purposes).
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 589a0f7..4f54eac 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 900038	/* Master, propagated to newvers */
+#define __FreeBSD_version 900039	/* Master, propagated to newvers */
 
 #ifdef _KERNEL
 #define	P_OSREL_SIGSEGV		700004
diff --git a/usr.sbin/ftp-proxy/ftp-proxy/Makefile b/usr.sbin/ftp-proxy/ftp-proxy/Makefile
index 773c25d..c21a107 100644
--- a/usr.sbin/ftp-proxy/ftp-proxy/Makefile
+++ b/usr.sbin/ftp-proxy/ftp-proxy/Makefile
@@ -5,14 +5,14 @@
 PROG=	ftp-proxy
 MAN=	ftp-proxy.8
 
-SRCS=   ftp-proxy.c filter.c
+SRCS=	ftp-proxy.c filter.c
 
 CFLAGS+= -I${.CURDIR}/../../../contrib/pf/libevent
 CFLAGS+= -I${.CURDIR}/../../../sys/contrib/pf
 
-DPADD=	${LIBEVENT}
-LDADD=	${LIBEVENT}
+LDADD+= ${LIBEVENT}
+DPADD+= ${LIBEVENT}
 
-WARNS?=	2
+WARNS?=	3
 
 .include 
-- 
cgit v1.1


From e20cfd48ae526e42061074896408997f5095d5a3 Mon Sep 17 00:00:00 2001
From: osa 
Date: Tue, 28 Jun 2011 12:32:24 +0000
Subject: Remove needless file due to Russia scraps DST in 2011. > Description
 of fields to fill in above:                     76 columns --| > PR:         
   If a GNATS PR is affected by the change. > Submitted by:  If someone else
 sent in the change. > Reviewed by:   If someone else reviewed your
 modification. > Approved by:   If you needed approval for this commit. >
 Obtained from: If the change is from a third party. > MFC after:     N
 [day[s]|week[s]|month[s]].  Request a reminder email. > Security:     
 Vulnerability reference (one per line) or description. > Empty fields above
 will be automatically removed.

M    calendars/ru_RU.KOI8-R/calendar.all
D    calendars/ru_RU.KOI8-R/calendar.msk
---
 usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.all |  1 -
 usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.msk | 16 ----------------
 2 files changed, 17 deletions(-)
 delete mode 100644 usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.msk

diff --git a/usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.all b/usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.all
index b2de01e..25b7b59 100644
--- a/usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.all
+++ b/usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.all
@@ -10,7 +10,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 
diff --git a/usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.msk b/usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.msk
deleted file mode 100644
index 5e27985..0000000
--- a/usr.bin/calendar/calendars/ru_RU.KOI8-R/calendar.msk
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * ðÅÒÅ×ÏÄ ÞÁÓÏ× ÄÌÑ ÍÏÓËÏ×ÓËÏÊ ×ÒÅÍÅÎÎÏÊ ÚÏÎÙ
- *
- * $FreeBSD$
- */
-
-#ifndef _ru_RU_KOI8_R_msk_
-#define _ru_RU_KOI8_R_msk_
-
-LANG=ru_RU.KOI8-R
-
-03/SunLast	îÁÞÁÌÏ ÍÏÓËÏ×ÓËÏÇÏ ÌÅÔÎÅÇÏ ×ÒÅÍÅÎÉ; ÞÁÓÙ ÐÅÒÅ×ÏÄÑÔÓÑ ×ÐÅÒÅÄ
-10/SunLast	ëÏÎÅà ÍÏÓËÏ×ÓËÏÇÏ ÌÅÔÎÅÇÏ ×ÒÅÍÅÎÉ; ÞÁÓÙ ÐÅÒÅ×ÏÄÑÔÓÑ ÎÁÚÁÄ
-
-#endif /* !_ru_RU_KOI8_R_msk_ */
-
-- 
cgit v1.1


From b1a34d6c3bddb3524356c692c71ec72458df5d2f Mon Sep 17 00:00:00 2001
From: hselasky 
Date: Tue, 28 Jun 2011 14:07:28 +0000
Subject: LibUSB v1.0: Need at least one frame when doing the dummy open else
 clear stall won't work in that case.

---
 lib/libusb/libusb10.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c
index fa50ea7..737e610 100644
--- a/lib/libusb/libusb10.c
+++ b/lib/libusb/libusb10.c
@@ -636,7 +636,7 @@ libusb_clear_halt(struct libusb20_device *pdev, uint8_t endpoint)
 		return (LIBUSB_ERROR_INVALID_PARAM);
 
 	CTX_LOCK(dev->ctx);
-	err = libusb20_tr_open(xfer, 0, 0, endpoint);
+	err = libusb20_tr_open(xfer, 0, 1, endpoint);
 	CTX_UNLOCK(dev->ctx);
 
 	if (err != 0 && err != LIBUSB20_ERROR_BUSY)
-- 
cgit v1.1


From 0b9b3ff55fe43a1809945421c3b1367da1896f0e Mon Sep 17 00:00:00 2001
From: pluknet 
Date: Tue, 28 Jun 2011 14:26:34 +0000
Subject: Run load_rc_config before stop_cmd definition, so that
 ${quotaoff_flags} is correctly expanded inside stop_cmd instead of getting
 nothing.

PR:		conf/157687
Reported by:	Dmitry Banschikov 
MFC after:	1 week
---
 etc/rc.d/quota | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/etc/rc.d/quota b/etc/rc.d/quota
index 6432f50..edc90ef 100755
--- a/etc/rc.d/quota
+++ b/etc/rc.d/quota
@@ -14,6 +14,7 @@
 
 name="quota"
 rcvar=`set_rcvar`
+load_rc_config $name
 start_cmd="quota_start"
 stop_cmd="/usr/sbin/quotaoff ${quotaoff_flags}"
 
@@ -30,5 +31,4 @@ quota_start()
 	echo ' done.'
 }
 
-load_rc_config $name
 run_rc_command "$1"
-- 
cgit v1.1


From 57a4978d94386cf63e9d3bb1f17241b75af936c7 Mon Sep 17 00:00:00 2001
From: marius 
Date: Tue, 28 Jun 2011 16:16:43 +0000
Subject: - In gem_reset_rx() also reset the RX MAC which is necessary in order
 to   get it out of a stuck condition that can be caused by
 GEM_MAC_RX_OVERFLOW. - In gem_reset_rxdma() call gem_setladrf() in order to
 reprogram the RX   filter and restore the previous content of
 GEM_MAC_RX_CONFIG. While at it   consistently use the newly introduced
 sc_mac_rxcfg throughout the driver   instead of reading the its old content.
 - Increment if_iqdrops instead of if_ierrors in case of RX buffer allocation 
  failure. - According to the GEM datasheet the RX MAC should also be disabled
 in   gem_setladrf() before changing its configuration. - Add error messages
 to gem_disable_{r,t}x() and take advantage of these   throughout the driver
 instead of duplicating their functionality all over   the place.

In joint forces with:	yongari
---
 sys/dev/gem/if_gem.c    | 101 +++++++++++++++++++++++++-----------------------
 sys/dev/gem/if_gemvar.h |   2 +
 2 files changed, 55 insertions(+), 48 deletions(-)

diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c
index 9ee43f2..e0df591 100644
--- a/sys/dev/gem/if_gem.c
+++ b/sys/dev/gem/if_gem.c
@@ -121,7 +121,7 @@ static void	gem_rint_timeout(void *arg);
 #endif
 static inline void gem_rxcksum(struct mbuf *m, uint64_t flags);
 static void	gem_rxdrain(struct gem_softc *sc);
-static void	gem_setladrf(struct gem_softc *sc);
+static void	gem_setladrf(struct gem_softc *sc, u_int enable);
 static void	gem_start(struct ifnet *ifp);
 static void	gem_start_locked(struct ifnet *ifp);
 static void	gem_stop(struct ifnet *ifp, int disable);
@@ -705,7 +705,7 @@ gem_reset_rx(struct gem_softc *sc)
 	 * Resetting while DMA is in progress can cause a bus hang, so we
 	 * disable DMA first.
 	 */
-	gem_disable_rx(sc);
+	(void)gem_disable_rx(sc);
 	GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 0);
 	GEM_BANK1_BARRIER(sc, GEM_RX_CONFIG, 4,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
@@ -715,7 +715,7 @@ gem_reset_rx(struct gem_softc *sc)
 	/* Wait 5ms extra. */
 	DELAY(5000);
 
-	/* Finally, reset the ERX. */
+	/* Reset the ERX. */
 	GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX);
 	GEM_BANK2_BARRIER(sc, GEM_RESET, 4,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
@@ -724,6 +724,16 @@ gem_reset_rx(struct gem_softc *sc)
 		device_printf(sc->sc_dev, "cannot reset receiver\n");
 		return (1);
 	}
+
+	/* Finally, reset RX MAC. */
+	GEM_BANK1_WRITE_4(sc, GEM_MAC_RXRESET, 1);
+	GEM_BANK1_BARRIER(sc, GEM_MAC_RXRESET, 4,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RXRESET, 1, 0)) {
+		device_printf(sc->sc_dev, "cannot reset RX MAC\n");
+		return (1);
+	}
+
 	return (0);
 }
 
@@ -766,12 +776,17 @@ gem_reset_rxdma(struct gem_softc *sc)
 	GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH,
 	    (3 * sc->sc_rxfifosize / 256) |
 	    ((sc->sc_rxfifosize / 256) << 12));
+	/*
+	 * Clear the RX filter and reprogram it.  This will also set the
+	 * current RX MAC configuration.
+	 */
+	gem_setladrf(sc, 0);
 	GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG,
 	    GEM_BANK1_READ_4(sc, GEM_RX_CONFIG) | GEM_RX_CONFIG_RXDMA_EN);
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK,
 	    GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT);
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG,
-	    GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) | GEM_MAC_RX_ENABLE);
+	    sc->sc_mac_rxcfg | GEM_MAC_RX_ENABLE);
 }
 
 static int
@@ -782,7 +797,7 @@ gem_reset_tx(struct gem_softc *sc)
 	 * Resetting while DMA is in progress can cause a bus hang, so we
 	 * disable DMA first.
 	 */
-	gem_disable_tx(sc);
+	(void)gem_disable_tx(sc);
 	GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, 0);
 	GEM_BANK1_BARRIER(sc, GEM_TX_CONFIG, 4,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
@@ -812,8 +827,10 @@ gem_disable_rx(struct gem_softc *sc)
 	    GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) & ~GEM_MAC_RX_ENABLE);
 	GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	return (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE,
-	    0));
+	if (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0))
+		return (1);
+	device_printf(sc->sc_dev, "cannot disable RX MAC\n");
+	return (0);
 }
 
 static int
@@ -824,8 +841,10 @@ gem_disable_tx(struct gem_softc *sc)
 	    GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG) & ~GEM_MAC_TX_ENABLE);
 	GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	return (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE,
-	    0));
+	if (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0))
+		return (1);
+	device_printf(sc->sc_dev, "cannot disable TX MAC\n");
+	return (0);
 }
 
 static int
@@ -960,7 +979,7 @@ gem_init_locked(struct gem_softc *sc)
 	gem_init_regs(sc);
 
 	/* step 5.  RX MAC registers & counters */
-	gem_setladrf(sc);
+	gem_setladrf(sc, 0);
 
 	/* step 6 & 7.  Program Descriptor Ring Base Addresses. */
 	/* NOTE: we use only 32-bit DMA addresses here. */
@@ -1050,21 +1069,14 @@ gem_init_locked(struct gem_softc *sc)
 	/* step 12.  RX_MAC Configuration Register */
 	v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG);
 	v |= GEM_MAC_RX_ENABLE | GEM_MAC_RX_STRIP_CRC;
-	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0);
-	GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0))
-		device_printf(sc->sc_dev, "cannot configure RX MAC\n");
+	(void)gem_disable_rx(sc);
+	sc->sc_mac_rxcfg = v & ~GEM_MAC_RX_ENABLE;
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v);
 
 	/* step 13.  TX_MAC Configuration Register */
 	v = GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG);
 	v |= GEM_MAC_TX_ENABLE;
-	GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0);
-	GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0))
-		device_printf(sc->sc_dev, "cannot configure TX MAC\n");
+	(void)gem_disable_tx(sc);
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v);
 
 	/* step 14.  Issue Transmit Pending command. */
@@ -1588,7 +1600,7 @@ gem_rint(struct gem_softc *sc)
 		 * the buffer that's already attached to this descriptor.
 		 */
 		if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) {
-			ifp->if_ierrors++;
+			ifp->if_iqdrops++;
 			GEM_INIT_RXDESC(sc, sc->sc_rxptr);
 			m = NULL;
 		}
@@ -2028,8 +2040,8 @@ gem_mii_statchg(device_t dev)
 	 * the GEM Gigabit Ethernet ASIC Specification.
 	 */
 
-	rxcfg = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG);
-	rxcfg &= ~(GEM_MAC_RX_CARR_EXTEND | GEM_MAC_RX_ENABLE);
+	rxcfg = sc->sc_mac_rxcfg;
+	rxcfg &= ~GEM_MAC_RX_CARR_EXTEND;
 	txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT;
 	if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0)
 		txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS;
@@ -2037,17 +2049,9 @@ gem_mii_statchg(device_t dev)
 		rxcfg |= GEM_MAC_RX_CARR_EXTEND;
 		txcfg |= GEM_MAC_TX_CARR_EXTEND;
 	}
-	GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0);
-	GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0))
-		device_printf(sc->sc_dev, "cannot disable TX MAC\n");
+	(void)gem_disable_tx(sc);
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, txcfg);
-	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0);
-	GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0))
-		device_printf(sc->sc_dev, "cannot disable RX MAC\n");
+	(void)gem_disable_rx(sc);
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, rxcfg);
 
 	v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG) &
@@ -2092,6 +2096,7 @@ gem_mii_statchg(device_t dev)
 		v |= GEM_MAC_XIF_FDPLX_LED;
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v);
 
+	sc->sc_mac_rxcfg = rxcfg;
 	if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
 	    (sc->sc_flags & GEM_LINK) != 0) {
 		GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG,
@@ -2147,7 +2152,7 @@ gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
 			    ((ifp->if_flags ^ sc->sc_ifflags) &
 			    (IFF_ALLMULTI | IFF_PROMISC)) != 0)
-				gem_setladrf(sc);
+				gem_setladrf(sc, 1);
 			else
 				gem_init_locked(sc);
 		} else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
@@ -2164,7 +2169,8 @@ gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
 		GEM_LOCK(sc);
-		gem_setladrf(sc);
+		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+			gem_setladrf(sc, 1);
 		GEM_UNLOCK(sc);
 		break;
 	case SIOCGIFMEDIA:
@@ -2189,7 +2195,7 @@ gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 }
 
 static void
-gem_setladrf(struct gem_softc *sc)
+gem_setladrf(struct gem_softc *sc, u_int enable)
 {
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ifmultiaddr *inm;
@@ -2199,24 +2205,20 @@ gem_setladrf(struct gem_softc *sc)
 
 	GEM_LOCK_ASSERT(sc, MA_OWNED);
 
-	/* Get the current RX configuration. */
-	v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG);
-
 	/*
-	 * Turn off promiscuous mode, promiscuous group mode (all multicast),
-	 * and hash filter.  Depending on the case, the right bit will be
-	 * enabled.
+	 * Turn off the RX MAC and the hash filter as required by the Sun GEM
+	 * programming restrictions.
 	 */
-	v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_HASH_FILTER |
-	    GEM_MAC_RX_PROMISC_GRP);
-
+	v = sc->sc_mac_rxcfg & GEM_MAC_RX_HASH_FILTER;
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v);
 	GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER,
-	    0))
-		device_printf(sc->sc_dev, "cannot disable RX hash filter\n");
+	if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER |
+	    GEM_MAC_RX_ENABLE, 0))
+		device_printf(sc->sc_dev,
+		    "cannot disable RX MAC or hash filter\n");
 
+	v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_PROMISC_GRP);
 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
 		v |= GEM_MAC_RX_PROMISCUOUS;
 		goto chipit;
@@ -2262,5 +2264,8 @@ gem_setladrf(struct gem_softc *sc)
 		    hash[i]);
 
  chipit:
+	sc->sc_mac_rxcfg = v;
+	if (enable)
+		v |= GEM_MAC_RX_ENABLE;
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v);
 }
diff --git a/sys/dev/gem/if_gemvar.h b/sys/dev/gem/if_gemvar.h
index 59cb582..d89a322 100644
--- a/sys/dev/gem/if_gemvar.h
+++ b/sys/dev/gem/if_gemvar.h
@@ -173,6 +173,8 @@ struct gem_softc {
 	u_int		sc_rxptr;	/* next ready RX descriptor/state */
 	u_int		sc_rxfifosize;	/* RX FIFO size (bytes) */
 
+	uint32_t	sc_mac_rxcfg;	/* RX MAC conf. % GEM_MAC_RX_ENABLE */
+
 	int		sc_ifflags;
 	u_long		sc_csum_features;
 };
-- 
cgit v1.1


From 7573a2a80c2735616e782ffa398130ee14a6efa2 Mon Sep 17 00:00:00 2001
From: marius 
Date: Tue, 28 Jun 2011 16:44:02 +0000
Subject: Fix typo in r223648 which was accidentally committed

---
 sys/dev/gem/if_gem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c
index e0df591..7f44f22 100644
--- a/sys/dev/gem/if_gem.c
+++ b/sys/dev/gem/if_gem.c
@@ -2209,7 +2209,7 @@ gem_setladrf(struct gem_softc *sc, u_int enable)
 	 * Turn off the RX MAC and the hash filter as required by the Sun GEM
 	 * programming restrictions.
 	 */
-	v = sc->sc_mac_rxcfg & GEM_MAC_RX_HASH_FILTER;
+	v = sc->sc_mac_rxcfg & ~GEM_MAC_RX_HASH_FILTER;
 	GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v);
 	GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-- 
cgit v1.1


From b1ee47f4ffcb3c8f187f44d0810f23c8df8613f8 Mon Sep 17 00:00:00 2001
From: trasz 
Date: Tue, 28 Jun 2011 19:59:46 +0000
Subject: Revert the mechanical change from 'file system' to 'filesystem',
 committed in r223429.  As bde@ pointed out, it was mostly backwards.

---
 sbin/growfs/growfs.8 | 38 +++++++++++++++++++-------------------
 sbin/growfs/growfs.c | 44 ++++++++++++++++++++++----------------------
 2 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/sbin/growfs/growfs.8 b/sbin/growfs/growfs.8
index 037814d..819e0bd 100644
--- a/sbin/growfs/growfs.8
+++ b/sbin/growfs/growfs.8
@@ -37,12 +37,12 @@
 .\" $TSHeader: src/sbin/growfs/growfs.8,v 1.3 2000/12/12 19:31:00 tomsoft Exp $
 .\" $FreeBSD$
 .\"
-.Dd June 22, 2011
+.Dd June 29, 2011
 .Dt GROWFS 8
 .Os
 .Sh NAME
 .Nm growfs
-.Nd expand an existing UFS filesystem
+.Nd expand an existing UFS file system
 .Sh SYNOPSIS
 .Nm
 .Op Fl Ny
@@ -58,8 +58,8 @@ Before starting
 .Nm
 the disk must be labeled to a bigger size using
 .Xr bsdlabel 8 .
-If you wish to grow a filesystem beyond the boundary of
-the slice it resides in, you must resize the slice using
+If you wish to grow a file system beyond the boundary of
+the slice it resides in, you must re-size the slice using
 .Xr gpart 8
 before running
 .Nm .
@@ -67,17 +67,17 @@ If you are using volumes you must enlarge them by using
 .Xr gvinum 8 .
 The
 .Nm
-utility extends the size of the filesystem on the specified special file.
+utility extends the size of the file system on the specified special file.
 Currently
 .Nm
-can only enlarge unmounted filesystems.
-Do not try enlarging a mounted filesystem, your system may panic and you will
-not be able to use the filesystem any longer.
+can only enlarge unmounted file systems.
+Do not try enlarging a mounted file system, your system may panic and you will
+not be able to use the file system any longer.
 Most of the
 .Xr newfs 8
 options cannot be changed by
 .Nm .
-In fact, you can only increase the size of the filesystem.
+In fact, you can only increase the size of the file system.
 Use
 .Xr tunefs 8
 for other changes.
@@ -86,8 +86,8 @@ The following options are available:
 .Bl -tag -width indent
 .It Fl N
 .Dq Test mode .
-Causes the new filesystem parameters to be printed out without actually
-enlarging the filesystem.
+Causes the new file system parameters to be printed out without actually
+enlarging the file system.
 .It Fl y
 .Dq Expert mode .
 Usually
@@ -102,12 +102,12 @@ So use this option with great care!
 .It Fl s Ar size
 Determines the
 .Ar size
-of the filesystem after enlarging in sectors.
+of the file system after enlarging in sectors.
 This value defaults to the size of the raw partition specified in
 .Ar special
 (in other words,
 .Nm
-will enlarge the filesystem to the size of the entire partition).
+will enlarge the file system to the size of the entire partition).
 .El
 .Sh EXAMPLES
 .Dl growfs -s 4194304 /dev/vinum/testvol
@@ -122,9 +122,9 @@ up to 2GB if there is enough space in
 .Xr ffsinfo 8 ,
 .Xr fsck 8 ,
 .Xr gpart 8 ,
+.Xr gvinum 8 ,
 .Xr newfs 8 ,
-.Xr tunefs 8 ,
-.Xr gvinum 8
+.Xr tunefs 8
 .Sh HISTORY
 The
 .Nm
@@ -144,12 +144,12 @@ There may be cases on
 .Fx
 3.x only, when
 .Nm
-does not recognize properly whether or not the filesystem is mounted and
+does not recognize properly whether or not the file system is mounted and
 exits with an error message.
 Then please use
 .Nm
 .Fl y
-if you are sure that the filesystem is not mounted.
+if you are sure that the file system is not mounted.
 It is also recommended to always use
 .Xr fsck 8
 after enlarging (just to be on the safe side).
@@ -183,8 +183,8 @@ on the first cylinder group to verify that
 in the CYLINDER SUMMARY (internal cs) of the CYLINDER GROUP
 .Em cgr0
 has enough blocks.
-As a rule of thumb for default filesystem parameters one block is needed for
-every 2 GB of total filesystem size.
+As a rule of thumb for default file system parameters one block is needed for
+every 2 GB of total file system size.
 .Pp
 Normally
 .Nm
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index 76a2841..148f8ca 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -160,7 +160,7 @@ static void	get_dev_size(int, int *);
 
 /* ************************************************************ growfs ***** */
 /*
- * Here we actually start growing the filesystem. We basically read the
+ * Here we actually start growing the file system. We basically read the
  * cylinder summary from the first cylinder group as we want to update
  * this on the fly during our various operations. First we handle the
  * changes in the former last cylinder group. Afterwards we create all new
@@ -231,7 +231,7 @@ growfs(int fsi, int fso, unsigned int Nflag)
 	updjcg(osblock.fs_ncg-1, modtime, fsi, fso, Nflag);
 
 	/*
-	 * Dump out summary information about filesystem.
+	 * Dump out summary information about file system.
 	 */
 #	define B2MBFACTOR (1 / (1024.0 * 1024.0))
 	printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n",
@@ -435,7 +435,7 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
 	if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) {
 		/*
 		 * This should never happen as we would have had that panic
-		 * already on filesystem creation
+		 * already on file system creation
 		 */
 		errx(37, "panic: cylinder group too big");
 	}
@@ -446,7 +446,7 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
 			acg.cg_cs.cs_nifree--;
 		}
 	/*
-	 * For the old filesystem, we have to initialize all the inodes.
+	 * For the old file system, we have to initialize all the inodes.
 	 */
 	if (sblock.fs_magic == FS_UFS1_MAGIC) {
 		bzero(iobuf, sblock.fs_bsize);
@@ -670,7 +670,7 @@ cond_bl_upd(ufs2_daddr_t *block, struct gfs_bpp *field, int fsi, int fso,
 /* ************************************************************ updjcg ***** */
 /*
  * Here we do all needed work for the former last cylinder group. It has to be
- * changed in any case, even if the filesystem ended exactly on the end of
+ * changed in any case, even if the file system ended exactly on the end of
  * this group, as there is some slightly inconsistent handling of the number
  * of cylinders in the cylinder group. We start again by reading the cylinder
  * group from disk. If the last block was not fully available, we first handle
@@ -780,7 +780,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
 	 * the rotational layout tables and the cluster summary.  This is
 	 * also done per fragment for the first new block if the old file
 	 * system end was not on a block boundary, per fragment for the new
-	 * last block if the new filesystem end is not on a block boundary,
+	 * last block if the new file system end is not on a block boundary,
 	 * and per block for all space in between.
 	 *
 	 * Handle the first new block here if it was partially available
@@ -804,7 +804,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
 			/*
 			 * Check if the fragment just created could join an
 			 * already existing fragment at the former end of the
-			 * filesystem.
+			 * file system.
 			 */
 			if(isblock(&sblock, cg_blksfree(&acg),
 			    ((osblock.fs_size - cgbase(&sblock, cylno))/
@@ -931,7 +931,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
  * Option (1) is considered to be less intrusive to the structure of the file-
  * system. So we try to stick to that whenever possible. If there is not enough
  * space in the cylinder group containing the cylinder summary we have to use
- * method (2). In case of active snapshots in the filesystem we probably can
+ * method (2). In case of active snapshots in the file system we probably can
  * completely avoid implementing copy on write if we stick to method (2) only.
  */
 static void
@@ -1287,7 +1287,7 @@ updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag)
 		/*
 		 * No cluster handling is needed here, as there was at least
 		 * one fragment in use by the cylinder summary in the old
-		 * filesystem.
+		 * file system.
 		 * No block-free counter handling here as this block was not
 		 * a free block.
 		 */
@@ -1597,7 +1597,7 @@ wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
 /*
  * Here we allocate a free block in the current cylinder group. It is assumed,
  * that acg contains the current cylinder group. As we may take a block from
- * somewhere in the filesystem we have to handle cluster summary here.
+ * somewhere in the file system we have to handle cluster summary here.
  */
 static ufs2_daddr_t
 alloc(void)
@@ -1939,9 +1939,9 @@ get_dev_size(int fd, int *size)
 /* ************************************************************** main ***** */
 /*
  * growfs(8)  is a utility which allows to increase the size of an existing
- * ufs filesystem. Currently this can only be done on unmounted filesystem.
+ * ufs file system. Currently this can only be done on unmounted file system.
  * It recognizes some command line options to specify the new desired size,
- * and it does some basic checkings. The old filesystem size is determined
+ * and it does some basic checkings. The old file system size is determined
  * and after some more checks like we can really access the new last block
  * on the disk etc. we calculate the new parameters for the superblock. After
  * having done this we just call growfs() which will do the work.  Before
@@ -1953,11 +1953,11 @@ get_dev_size(int fd, int *size)
  * are lucky, then we only have to handle our blocks to be relocated in that
  * way.
  * Also we have to consider in what order we actually update the critical
- * data structures of the filesystem to make sure, that in case of a disaster
+ * data structures of the file system to make sure, that in case of a disaster
  * fsck(8) is still able to restore any lost data.
  * The foreseen last step then will be to provide for growing even mounted
- * filesystems. There we have to extend the mount() system call to provide
- * userland access to the filesystem locking facility.
+ * file systems. There we have to extend the mount() system call to provide
+ * userland access to the file system locking facility.
  */
 int
 main(int argc, char **argv)
@@ -2088,7 +2088,7 @@ main(int argc, char **argv)
     }
 
 	/*
-	 * Check if that partition is suitable for growing a filesystem.
+	 * Check if that partition is suitable for growing a file system.
 	 */
 	if (p_size < 1) {
 		errx(1, "partition is unavailable");
@@ -2146,7 +2146,7 @@ main(int argc, char **argv)
 	if(ExpertFlag == 0) {
 		for(j=0; j
Date: Tue, 28 Jun 2011 20:57:54 +0000
Subject: Make activemap_write_start/complete check the keepdirty list, when
 stating if we need to update activemap on disk. This makes keepdirty serve
 its purpose -- to reduce number of metadata updates.

Discussed with:	pjd
Approved by:	pjd (mentor)
---
 sbin/hastd/activemap.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/sbin/hastd/activemap.c b/sbin/hastd/activemap.c
index 2777ac5..127b2c8 100644
--- a/sbin/hastd/activemap.c
+++ b/sbin/hastd/activemap.c
@@ -205,7 +205,7 @@ keepdirty_find(struct activemap *amp, int extent)
 	return (kd);
 }
 
-static void
+static bool
 keepdirty_add(struct activemap *amp, int extent)
 {
 	struct keepdirty *kd;
@@ -217,7 +217,7 @@ keepdirty_add(struct activemap *amp, int extent)
 		 */
 		TAILQ_REMOVE(&->am_keepdirty, kd, kd_next);
 		TAILQ_INSERT_HEAD(&->am_keepdirty, kd, kd_next);
-		return;
+		return (false);
 	}
 	/*
 	 * Add new element, but first remove the most unused one if
@@ -238,6 +238,8 @@ keepdirty_add(struct activemap *amp, int extent)
 		amp->am_nkeepdirty++;
 		TAILQ_INSERT_HEAD(&->am_keepdirty, kd, kd_next);
 	}
+
+	return (true);
 }
 
 static void
@@ -308,9 +310,9 @@ activemap_write_start(struct activemap *amp, off_t offset, off_t length)
 			assert(!bit_test(amp->am_memmap, ext));
 			bit_set(amp->am_memmap, ext);
 			amp->am_ndirty++;
-			modified = true;
 		}
-		keepdirty_add(amp, ext);
+		if (keepdirty_add(amp, ext))
+			modified = true;
 	}
 
 	return (modified);
@@ -345,7 +347,8 @@ activemap_write_complete(struct activemap *amp, off_t offset, off_t length)
 		if (--amp->am_memtab[ext] == 0) {
 			bit_clear(amp->am_memmap, ext);
 			amp->am_ndirty--;
-			modified = true;
+			if (keepdirty_find(amp, ext) == NULL)
+				modified = true;
 		}
 	}
 
-- 
cgit v1.1


From 82faa3e64109fa8b1a1833758bd1404e494548b2 Mon Sep 17 00:00:00 2001
From: trociny 
Date: Tue, 28 Jun 2011 21:01:32 +0000
Subject: Check the returned value of activemap_write_complete() and update
 matadata on disk if needed. This should fix a potential case when extents are
 cleared in activemap but metadata is not updated on disk.

Suggested by:	pjd
Approved by:	pjd (mentor)
---
 sbin/hastd/primary.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c
index af0f353..e1f2ba4 100644
--- a/sbin/hastd/primary.c
+++ b/sbin/hastd/primary.c
@@ -1687,8 +1687,11 @@ ggate_send_thread(void *arg)
 		}
 		if (ggio->gctl_error == 0 && ggio->gctl_cmd == BIO_WRITE) {
 			mtx_lock(&res->hr_amp_lock);
-			activemap_write_complete(res->hr_amp,
-			    ggio->gctl_offset, ggio->gctl_length);
+			if (activemap_write_complete(res->hr_amp,
+				ggio->gctl_offset, ggio->gctl_length)) {
+				res->hr_stat_activemap_update++;
+				(void)hast_activemap_flush(res);
+			}
 			mtx_unlock(&res->hr_amp_lock);
 		}
 		if (ggio->gctl_cmd == BIO_WRITE) {
-- 
cgit v1.1


From 0393f389af4d3d0b054c79ffd0af82e081218262 Mon Sep 17 00:00:00 2001
From: rmacklem 
Date: Tue, 28 Jun 2011 22:52:38 +0000
Subject: Fix the new NFSv4 client so that it doesn't fill the cached mode
 attribute in as 0 when doing writes. The change adds the Mode attribute plus
 the others except Owner and Owner_group to the list requested by the NFSv4
 Write Operation. This fixed a problem where an executable file built by "cc"
 would get mode 0111 instead of 0755 for some NFSv4 servers. Found at the
 recent NFSv4 interoperability Bakeathon.

Tested by:	tdh at excfb.com
MFC after:	2 weeks
---
 sys/fs/nfs/nfsproto.h           | 15 ++++++++++++---
 sys/fs/nfsclient/nfs_clport.c   |  1 +
 sys/fs/nfsclient/nfs_clrpcops.c |  4 ++--
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h
index a15f93b..5ae2e3d 100644
--- a/sys/fs/nfs/nfsproto.h
+++ b/sys/fs/nfs/nfsproto.h
@@ -868,15 +868,24 @@ struct nfsv3_sattr {
  * NFSATTRBIT_WRITEGETATTR0 - bits 0<->31
  */
 #define	NFSATTRBIT_WRITEGETATTR0					\
- 	(NFSATTRBM_CHANGE |						\
+ 	(NFSATTRBM_SUPPORTEDATTRS |					\
+ 	NFSATTRBM_TYPE |						\
+ 	NFSATTRBM_CHANGE |						\
  	NFSATTRBM_SIZE |						\
- 	NFSATTRBM_FSID)
+ 	NFSATTRBM_FSID |						\
+ 	NFSATTRBM_FILEID |						\
+ 	NFSATTRBM_MAXREAD)
 
 /*
  * NFSATTRBIT_WRITEGETATTR1 - bits 32<->63
  */
 #define	NFSATTRBIT_WRITEGETATTR1					\
- 	(NFSATTRBM_TIMEMETADATA |					\
+ 	(NFSATTRBM_MODE |						\
+ 	NFSATTRBM_NUMLINKS |						\
+ 	NFSATTRBM_RAWDEV |						\
+ 	NFSATTRBM_SPACEUSED |						\
+ 	NFSATTRBM_TIMEACCESS |						\
+ 	NFSATTRBM_TIMEMETADATA |					\
  	NFSATTRBM_TIMEMODIFY)
 
 /*
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 0538382..4a95887 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -388,6 +388,7 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
 		np->n_vattr.na_mtime = nap->na_mtime;
 		np->n_vattr.na_ctime = nap->na_ctime;
 		np->n_vattr.na_fsid = nap->na_fsid;
+		np->n_vattr.na_mode = nap->na_mode;
 	} else {
 		NFSBCOPY((caddr_t)nap, (caddr_t)&np->n_vattr,
 		    sizeof (struct nfsvattr));
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 5d83d0b..ee73882 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -1527,8 +1527,8 @@ nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,
 		 * deadlock, is that the upcall times out and allows
 		 * the write to complete. However, progress is so slow
 		 * that it might just as well be deadlocked.
-		 * So, we just get the attributes that change with each
-		 * write Op.
+		 * As such, we get the rest of the attributes, but not
+		 * Owner or Owner_group.
 		 * nb: nfscl_loadattrcache() needs to be told that these
 		 *     partial attributes from a write rpc are being
 		 *     passed in, via a argument flag.
-- 
cgit v1.1


From bf194e6c5158aabcaf6a7b104dcc869fe1e41b31 Mon Sep 17 00:00:00 2001
From: ae 
Date: Wed, 29 Jun 2011 05:41:14 +0000
Subject: Initialize elements of state array when creating the GPT table. This
 fixes the problem, when the secondary GPT header is not erased when partition
 table destroyed. Move equal operations from g_part_gpt_create and
 g_part_gpt_recover to the separate function g_gpt_set_defaults.

Reported by:	dwhite
MFC after:	1 week
---
 sys/geom/part/g_part_gpt.c | 67 +++++++++++++++++++++++-----------------------
 1 file changed, 33 insertions(+), 34 deletions(-)

diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index 9e897a4..667a8d6 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -88,6 +88,7 @@ struct g_part_gpt_entry {
 
 static void g_gpt_printf_utf16(struct sbuf *, uint16_t *, size_t);
 static void g_gpt_utf8_to_utf16(const uint8_t *, uint16_t *, size_t);
+static void g_gpt_set_defaults(struct g_part_table *, struct g_provider *);
 
 static int g_part_gpt_add(struct g_part_table *, struct g_part_entry *,
     struct g_part_parms *);
@@ -493,12 +494,7 @@ g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp)
 	table->mbr[DOSPARTOFF + 6] = 0xff;		/* esect */
 	table->mbr[DOSPARTOFF + 7] = 0xff;		/* ecyl */
 	le32enc(table->mbr + DOSPARTOFF + 8, 1);	/* start */
-	le32enc(table->mbr + DOSPARTOFF + 12, MIN(last, 0xffffffffLL));
-
-	table->lba[GPT_ELT_PRIHDR] = 1;
-	table->lba[GPT_ELT_PRITBL] = 2;
-	table->lba[GPT_ELT_SECHDR] = last;
-	table->lba[GPT_ELT_SECTBL] = last - tblsz;
+	le32enc(table->mbr + DOSPARTOFF + 12, MIN(last, UINT32_MAX));
 
 	/* Allocate space for the header */
 	table->hdr = g_malloc(sizeof(struct gpt_hdr), M_WAITOK | M_ZERO);
@@ -506,14 +502,11 @@ g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp)
 	bcopy(GPT_HDR_SIG, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig));
 	table->hdr->hdr_revision = GPT_HDR_REVISION;
 	table->hdr->hdr_size = offsetof(struct gpt_hdr, padding);
-	table->hdr->hdr_lba_start = 2 + tblsz;
-	table->hdr->hdr_lba_end = last - tblsz - 1;
 	kern_uuidgen(&table->hdr->hdr_uuid, 1);
 	table->hdr->hdr_entries = basetable->gpt_entries;
 	table->hdr->hdr_entsz = sizeof(struct gpt_ent);
 
-	basetable->gpt_first = table->hdr->hdr_lba_start;
-	basetable->gpt_last = table->hdr->hdr_lba_end;
+	g_gpt_set_defaults(basetable, pp);
 	return (0);
 }
 
@@ -815,32 +808,10 @@ g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp)
 static int
 g_part_gpt_recover(struct g_part_table *basetable)
 {
-	struct g_part_gpt_table *table;
-	struct g_provider *pp;
-	uint64_t last;
-	size_t tblsz;
-
-	table = (struct g_part_gpt_table *)basetable;
-	pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
-	last = pp->mediasize / pp->sectorsize - 1;
-	tblsz = (table->hdr->hdr_entries * table->hdr->hdr_entsz +
-	    pp->sectorsize - 1) / pp->sectorsize;
-
-	table->lba[GPT_ELT_PRIHDR] = 1;
-	table->lba[GPT_ELT_PRITBL] = 2;
-	table->lba[GPT_ELT_SECHDR] = last;
-	table->lba[GPT_ELT_SECTBL] = last - tblsz;
-	table->state[GPT_ELT_PRIHDR] = GPT_STATE_OK;
-	table->state[GPT_ELT_PRITBL] = GPT_STATE_OK;
-	table->state[GPT_ELT_SECHDR] = GPT_STATE_OK;
-	table->state[GPT_ELT_SECTBL] = GPT_STATE_OK;
-	table->hdr->hdr_lba_start = 2 + tblsz;
-	table->hdr->hdr_lba_end = last - tblsz - 1;
 
-	basetable->gpt_first = table->hdr->hdr_lba_start;
-	basetable->gpt_last = table->hdr->hdr_lba_end;
+	g_gpt_set_defaults(basetable,
+	    LIST_FIRST(&basetable->gpt_gp->consumer)->provider);
 	basetable->gpt_corrupt = 0;
-
 	return (0);
 }
 
@@ -1039,6 +1010,34 @@ g_part_gpt_write(struct g_part_table *basetable, struct g_consumer *cp)
 }
 
 static void
+g_gpt_set_defaults(struct g_part_table *basetable, struct g_provider *pp)
+{
+	struct g_part_gpt_table *table;
+	quad_t last;
+	size_t tblsz;
+
+	table = (struct g_part_gpt_table *)basetable;
+	last = pp->mediasize / pp->sectorsize - 1;
+	tblsz = (basetable->gpt_entries * sizeof(struct gpt_ent) +
+	    pp->sectorsize - 1) / pp->sectorsize;
+
+	table->lba[GPT_ELT_PRIHDR] = 1;
+	table->lba[GPT_ELT_PRITBL] = 2;
+	table->lba[GPT_ELT_SECHDR] = last;
+	table->lba[GPT_ELT_SECTBL] = last - tblsz;
+	table->state[GPT_ELT_PRIHDR] = GPT_STATE_OK;
+	table->state[GPT_ELT_PRITBL] = GPT_STATE_OK;
+	table->state[GPT_ELT_SECHDR] = GPT_STATE_OK;
+	table->state[GPT_ELT_SECTBL] = GPT_STATE_OK;
+
+	table->hdr->hdr_lba_start = 2 + tblsz;
+	table->hdr->hdr_lba_end = last - tblsz - 1;
+
+	basetable->gpt_first = table->hdr->hdr_lba_start;
+	basetable->gpt_last = table->hdr->hdr_lba_end;
+}
+
+static void
 g_gpt_printf_utf16(struct sbuf *sb, uint16_t *str, size_t len)
 {
 	u_int bo;
-- 
cgit v1.1


From 083452d2ebafcca278de8826484fad544c996baa Mon Sep 17 00:00:00 2001
From: ae 
Date: Wed, 29 Jun 2011 06:45:44 +0000
Subject: Improve error reporting. Use corresponding error message when file to
 be preprocessed is missing. Also suggest to use absolute pathname if -p
 option is specified.

PR:             bin/156653
MFC after:      2 weeks
---
 sbin/ipfw/main.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c
index 109b62b..433ce7d 100644
--- a/sbin/ipfw/main.c
+++ b/sbin/ipfw/main.c
@@ -262,7 +262,7 @@ ipfw_main(int oldac, char **oldav)
 	save_av = av;
 
 	optind = optreset = 1;	/* restart getopt() */
-	while ((ch = getopt(ac, av, "abcdefhinNqs:STtv")) != -1)
+	while ((ch = getopt(ac, av, "abcdefhinNp:qs:STtv")) != -1)
 		switch (ch) {
 		case 'a':
 			do_acct = 1;
@@ -306,6 +306,10 @@ ipfw_main(int oldac, char **oldav)
 			co.do_resolv = 1;
 			break;
 
+		case 'p':
+			errx(EX_USAGE, "An absolute pathname must be used "
+			    "with -p option.");
+
 		case 'q':
 			co.do_quiet = 1;
 			break;
@@ -603,9 +607,12 @@ main(int ac, char *av[])
 	 * as a file to be preprocessed.
 	 */
 
-	if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
-		ipfw_readfile(ac, av);
-	else {
+	if (ac > 1 && av[ac - 1][0] == '/') {
+		if (access(av[ac - 1], R_OK) == 0)
+			ipfw_readfile(ac, av);
+		else
+			err(EX_USAGE, "pathname: %s", av[ac - 1]);
+	} else {
 		if (ipfw_main(ac, av)) {
 			errx(EX_USAGE,
 			    "usage: ipfw [options]\n"
-- 
cgit v1.1


From 82c1b6015602eb2b9a077e04bd58c8a4d5401e4f Mon Sep 17 00:00:00 2001
From: avg 
Date: Wed, 29 Jun 2011 08:28:39 +0000
Subject: revert r222723: wrong change was committed

The commit intended to add SNDCTL_DSP_HALT, but actually added
SNDCTL_SEQ_HALT, which is not defined in the OSS specs.

Reported by:	Pan Tsu 
Pointyhat to:	gerald, avg
---
 sys/sys/soundcard.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/sys/sys/soundcard.h b/sys/sys/soundcard.h
index a6817df..c4cfc27 100644
--- a/sys/sys/soundcard.h
+++ b/sys/sys/soundcard.h
@@ -311,8 +311,7 @@ typedef struct _snd_capabilities {
  * IOCTL Commands for /dev/sequencer
  */
 
-#define SNDCTL_SEQ_HALT		_IO  ('Q', 0)
-#define SNDCTL_SEQ_RESET	SNDCTL_SEQ_HALT	/* Historic interface */
+#define SNDCTL_SEQ_RESET	_IO  ('Q', 0)
 #define SNDCTL_SEQ_SYNC		_IO  ('Q', 1)
 #define SNDCTL_SYNTH_INFO	_IOWR('Q', 2, struct synth_info)
 #define SNDCTL_SEQ_CTRLRATE	_IOWR('Q', 3, int) /* Set/get timer res.(hz) */
-- 
cgit v1.1


From 25754c328739d958c8e3d2eb1a045500af313d3f Mon Sep 17 00:00:00 2001
From: avg 
Date: Wed, 29 Jun 2011 08:32:37 +0000
Subject: add SNDCTL_DSP_HALT specified by OSS

This is really a new name for SNDCTL_DSP_RESET.
And this what commit r222723 should really have been in the first place.

PR:		kern/156874
Submitted by:	gerald
MFC after:	1 week
---
 sys/sys/soundcard.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/sys/soundcard.h b/sys/sys/soundcard.h
index c4cfc27..2916287 100644
--- a/sys/sys/soundcard.h
+++ b/sys/sys/soundcard.h
@@ -775,7 +775,8 @@ typedef struct {
  * IOCTL commands for /dev/dsp and /dev/audio
  */
 
-#define SNDCTL_DSP_RESET	_IO  ('P', 0)
+#define SNDCTL_DSP_HALT		_IO  ('P', 0)
+#define SNDCTL_DSP_RESET	SNDCTL_DSP_HALT
 #define SNDCTL_DSP_SYNC		_IO  ('P', 1)
 #define SNDCTL_DSP_SPEED	_IOWR('P', 2, int)
 #define SNDCTL_DSP_STEREO	_IOWR('P', 3, int)
-- 
cgit v1.1


From 93c32fd0711f841f49c0349d8c693ccc83913e1d Mon Sep 17 00:00:00 2001
From: kevlo 
Date: Wed, 29 Jun 2011 09:35:40 +0000
Subject: Typo

Submitted by:	Damjan Marion 
MFC after:	3 days
---
 sys/arm/mv/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sys/arm/mv/common.c b/sys/arm/mv/common.c
index 16bd325..09da857 100644
--- a/sys/arm/mv/common.c
+++ b/sys/arm/mv/common.c
@@ -122,7 +122,7 @@ static struct soc_node_spec soc_nodes[] = {
 	{ "mrvl,sata", &decode_win_sata_setup, NULL },
 	{ "mrvl,xor", &decode_win_xor_setup, &decode_win_xor_dump },
 	{ "mrvl,idma", &decode_win_idma_setup, &decode_win_idma_dump },
-	{ "mvrl,pcie", &decode_win_pcie_setup, NULL },
+	{ "mrvl,pcie", &decode_win_pcie_setup, NULL },
 	{ NULL, NULL, NULL },
 };
 
-- 
cgit v1.1


From 6b5f802b89475290bd6d581f19f00d0326038be1 Mon Sep 17 00:00:00 2001
From: ae 
Date: Wed, 29 Jun 2011 10:06:58 +0000
Subject: Add new rule actions "call" and "return" to ipfw. They make possible
 to organize subroutines with rules.

The "call" action saves the current rule number in the internal
stack and rules processing continues from the first rule with
specified number (similar to skipto action). If later a rule with
"return" action is encountered, the processing returns to the first
rule with number of "call" rule saved in the stack plus one or higher.

Submitted by:	Vadim Goncharov
Discussed by:	ipfw@, luigi@
---
 sbin/ipfw/ipfw.8                 |  89 ++++++++++++++++++++++++++++-
 sbin/ipfw/ipfw2.c                |  16 ++++++
 sbin/ipfw/ipfw2.h                |   2 +
 sys/netinet/ip_fw.h              |   8 +++
 sys/netinet/ip_var.h             |   1 +
 sys/netinet/ipfw/ip_fw2.c        | 117 +++++++++++++++++++++++++++++++++++++++
 sys/netinet/ipfw/ip_fw_log.c     |   7 +++
 sys/netinet/ipfw/ip_fw_sockopt.c |   1 +
 8 files changed, 240 insertions(+), 1 deletion(-)

diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 4a22320..6fc12c8 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 14, 2011
+.Dd June 29, 2011
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -822,6 +822,78 @@ skipto, but care should be used, as no destination caching
 is possible in this case so the rules are always walked to find it,
 starting from the 
 .Cm skipto .
+.It Cm call Ar number | tablearg
+The current rule number is saved in the internal stack and
+ruleset processing continues with the first rule numbered
+.Ar number
+or higher.
+If later a rule with the
+.Cm return
+action is encountered, the processing returns to the first rule
+with number of this
+.Cm call
+rule plus one or higher
+(the same behaviour as with packets returning from
+.Xr divert 4
+socket after a
+.Cm divert
+action).
+This could be used to make somewhat like an assembly language
+.Dq subroutine
+calls to rules with common checks for different interfaces, etc.
+.Pp
+Rule with any number could be called, not just forward jumps as with
+.Cm skipto .
+So, to prevent endless loops in case of mistakes, both
+.Cm call
+and
+.Cm return
+actions don't do any jumps and simply go to the next rule if memory
+can't be allocated or stack overflowed/undeflowed.
+.Pp
+Internally stack for rule numbers is implemented using
+.Xr mbuf_tags 9
+facility and currently has size of 16 entries.
+As mbuf tags are lost when packet leaves the kernel,
+.Cm divert
+should not be used in subroutines to avoid endless loops
+and other undesired effects.
+.It Cm return
+Takes rule number saved to internal stack by the last
+.Cm call
+action and returns ruleset processing to the first rule
+with number greater than number of corresponding
+.Cm call
+rule. See description of the
+.Cm call
+action for more details.
+.Pp
+Note that
+.Cm return
+rules usually end a
+.Dq subroutine
+and thus are unconditional, but
+.Nm
+command-line utility currently requires every action except
+.Cm check-state
+to have body.
+While it is sometimes useful to return only on some packets,
+usually you want to print just
+.Dq return
+for readability.
+A workaround for this is to use new syntax and
+.Fl c
+switch:
+.Pp
+.Bd -literal -offset indent
+# Add a rule without actual body
+ipfw add 2999 return via any
+
+# List rules without "from any to any" part
+ipfw -c list
+.Ed
+.Pp
+This cosmetic annoyance may be fixed in future releases.
 .It Cm tee Ar port
 Send a copy of packets matching this rule to the
 .Xr divert 4
@@ -3253,3 +3325,18 @@ for the respective conversations.
 To avoid failures of network error detection and path MTU discovery,
 ICMP error messages may need to be allowed explicitly through static
 rules.
+.Pp
+Rules using
+.Cm call
+and
+.Cm return
+actions may lead to confusing behaviour if ruleset has mistakes,
+and/or interaction with other subsystems (netgraph, dummynet, etc.) is used.
+One possible case for this is packet leaving
+.Nm
+in subroutine on the input pass, while later on output encountering unpaired
+.Cm return
+first.
+As the call stack is kept intact after input pass, packet will suddenly
+return to the rule number used on input pass, not on output one.
+Order of processing should be checked carefully to avoid such mistakes.
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 64e5eb1..e259f5e 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -214,6 +214,8 @@ static struct _s_x rule_actions[] = {
 	{ "nat",		TOK_NAT },
 	{ "reass",		TOK_REASS },
 	{ "setfib",		TOK_SETFIB },
+	{ "call",		TOK_CALL },
+	{ "return",		TOK_RETURN },
 	{ NULL, 0 }	/* terminator */
 };
 
@@ -1136,6 +1138,13 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
 			printf("reass");
 			break;
 
+		case O_CALLRETURN:
+			if (cmd->len & F_NOT)
+				printf("return");
+			else
+				PRINT_UINT_ARG("call ", cmd->arg1);
+			break;
+
 		default:
 			printf("** unrecognized action %d len %d ",
 				cmd->opcode, cmd->len);
@@ -2771,6 +2780,9 @@ ipfw_add(char *av[])
 		goto chkarg;
 	case TOK_TEE:
 		action->opcode = O_TEE;
+		goto chkarg;
+	case TOK_CALL:
+		action->opcode = O_CALLRETURN;
 chkarg:
 		if (!av[0])
 			errx(EX_USAGE, "missing argument for %s", *(av - 1));
@@ -2863,6 +2875,10 @@ chkarg:
 		action->opcode = O_REASS;
 		break;
 
+	case TOK_RETURN:
+		fill_cmd(action, O_CALLRETURN, F_NOT, 0);
+		break;
+
 	default:
 		errx(EX_DATAERR, "invalid action %s\n", av[-1]);
 	}
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 9562f32..bade0dd 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -99,6 +99,8 @@ enum tokens {
 	TOK_CHECKSTATE,
 	TOK_NAT,
 	TOK_REASS,
+	TOK_CALL,
+	TOK_RETURN,
 
 	TOK_ALTQ,
 	TOK_LOG,
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 06e107c..ff3a67f 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -57,6 +57,12 @@
 #define IP_FW_TABLEARG		65535	/* XXX should use 0 */
 
 /*
+ * Number of entries in the call stack of the call/return commands.
+ * Call stack currently is an uint16_t array with rule numbers.
+ */
+#define	IPFW_CALLSTACK_SIZE	16
+
+/*
  * The kernel representation of ipfw rules is made of a list of
  * 'instructions' (for all practical purposes equivalent to BPF
  * instructions), which specify which fields of the packet
@@ -195,6 +201,8 @@ enum ipfw_opcodes {		/* arguments (4 byte each)	*/
 	
 	O_SOCKARG,		/* socket argument */
 
+	O_CALLRETURN,		/* arg1=called rule number */
+
 	O_LAST_OPCODE		/* not an opcode!		*/
 };
 
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index e993279..cd30093 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -286,6 +286,7 @@ enum {
 };
 #define MTAG_IPFW	1148380143	/* IPFW-tagged cookie */
 #define MTAG_IPFW_RULE	1262273568	/* rule reference */
+#define	MTAG_IPFW_CALL	1308397630	/* call stack */
 
 struct ip_fw_args;
 typedef int	(*ip_fw_chk_ptr_t)(struct ip_fw_args *args);
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index 48837a7..4e25f9a 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -2095,6 +2095,123 @@ do {								\
 			    continue;
 			    break;	/* not reached */
 
+			case O_CALLRETURN: {
+				/*
+				 * Implementation of `subroutine' call/return,
+				 * in the stack carried in an mbuf tag. This
+				 * is different from `skipto' in that any call
+				 * address is possible (`skipto' must prevent
+				 * backward jumps to avoid endless loops).
+				 * We have `return' action when F_NOT flag is
+				 * present. The `m_tag_id' field is used as
+				 * stack pointer.
+				 */
+				struct m_tag *mtag;
+				uint16_t jmpto, *stack;
+
+#define	IS_CALL		((cmd->len & F_NOT) == 0)
+#define	IS_RETURN	((cmd->len & F_NOT) != 0)
+				/*
+				 * Hand-rolled version of m_tag_locate() with
+				 * wildcard `type'.
+				 * If not already tagged, allocate new tag.
+				 */
+				mtag = m_tag_first(m);
+				while (mtag != NULL) {
+					if (mtag->m_tag_cookie ==
+					    MTAG_IPFW_CALL)
+						break;
+					mtag = m_tag_next(m, mtag);
+				}
+				if (mtag == NULL && IS_CALL) {
+					mtag = m_tag_alloc(MTAG_IPFW_CALL, 0,
+					    IPFW_CALLSTACK_SIZE *
+					    sizeof(uint16_t), M_NOWAIT);
+					if (mtag != NULL)
+						m_tag_prepend(m, mtag);
+				}
+
+				/*
+				 * On error both `call' and `return' just
+				 * continue with next rule.
+				 */
+				if (IS_RETURN && (mtag == NULL ||
+				    mtag->m_tag_id == 0)) {
+					l = 0;		/* exit inner loop */
+					break;
+				}
+				if (IS_CALL && (mtag == NULL ||
+				    mtag->m_tag_id >= IPFW_CALLSTACK_SIZE)) {
+					printf("ipfw: call stack error, "
+					    "go to next rule\n");
+					l = 0;		/* exit inner loop */
+					break;
+				}
+
+				f->pcnt++;	/* update stats */
+				f->bcnt += pktlen;
+				f->timestamp = time_uptime;
+				stack = (uint16_t *)(mtag + 1);
+
+				/*
+				 * The `call' action may use cached f_pos
+				 * (in f->next_rule), whose version is written
+				 * in f->next_rule.
+				 * The `return' action, however, doesn't have
+				 * fixed jump address in cmd->arg1 and can't use
+				 * cache.
+				 */
+				if (IS_CALL) {
+					stack[mtag->m_tag_id] = f->rulenum;
+					mtag->m_tag_id++;
+					if (cmd->arg1 != IP_FW_TABLEARG &&
+					    (uintptr_t)f->x_next == chain->id) {
+						f_pos = (uintptr_t)f->next_rule;
+					} else {
+						jmpto = (cmd->arg1 ==
+						    IP_FW_TABLEARG) ? tablearg:
+						    cmd->arg1;
+						f_pos = ipfw_find_rule(chain,
+						    jmpto, 0);
+						/* update the cache */
+						if (cmd->arg1 !=
+						    IP_FW_TABLEARG) {
+							f->next_rule =
+							    (void *)(uintptr_t)
+							    f_pos;
+							f->x_next =
+							    (void *)(uintptr_t)
+							    chain->id;
+						}
+					}
+				} else {	/* `return' action */
+					mtag->m_tag_id--;
+					jmpto = stack[mtag->m_tag_id] + 1;
+					f_pos = ipfw_find_rule(chain, jmpto, 0);
+				}
+
+				/*
+				 * Skip disabled rules, and re-enter
+				 * the inner loop with the correct
+				 * f_pos, f, l and cmd.
+				 * Also clear cmdlen and skip_or
+				 */
+				for (; f_pos < chain->n_rules - 1 &&
+				    (V_set_disable &
+				    (1 << chain->map[f_pos]->set)); f_pos++)
+					;
+				/* Re-enter the inner loop at the dest rule. */
+				f = chain->map[f_pos];
+				l = f->cmd_len;
+				cmd = f->cmd;
+				cmdlen = 0;
+				skip_or = 0;
+				continue;
+				break;	/* NOTREACHED */
+			}
+#undef IS_CALL
+#undef IS_RETURN
+
 			case O_REJECT:
 				/*
 				 * Drop the packet and send a reject notice
diff --git a/sys/netinet/ipfw/ip_fw_log.c b/sys/netinet/ipfw/ip_fw_log.c
index 3560e13..2b55a38 100644
--- a/sys/netinet/ipfw/ip_fw_log.c
+++ b/sys/netinet/ipfw/ip_fw_log.c
@@ -304,6 +304,13 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
 		case O_REASS:
 			action = "Reass";
 			break;
+		case O_CALLRETURN:
+			if (cmd->len & F_NOT)
+				action = "Return";
+			else
+				snprintf(SNPARGS(action2, 0), "Call %d",
+				    cmd->arg1);
+			break;
 		default:
 			action = "UNKNOWN";
 			break;
diff --git a/sys/netinet/ipfw/ip_fw_sockopt.c b/sys/netinet/ipfw/ip_fw_sockopt.c
index 2347456..1432858 100644
--- a/sys/netinet/ipfw/ip_fw_sockopt.c
+++ b/sys/netinet/ipfw/ip_fw_sockopt.c
@@ -752,6 +752,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
 #endif
 		case O_SKIPTO:
 		case O_REASS:
+		case O_CALLRETURN:
 check_size:
 			if (cmdlen != F_INSN_SIZE(ipfw_insn))
 				goto bad_size;
-- 
cgit v1.1


From 385c8843b33e10d6ea1f996fb4be1f65994984fb Mon Sep 17 00:00:00 2001
From: bz 
Date: Wed, 29 Jun 2011 13:01:10 +0000
Subject: In case ntp cannot resolve a hostname on startup it will queue the
 entry for resolving by a child process that, upon success, will add the entry
 to the config of the running running parent process.

Unfortunately there are a couple of bugs with this, fixed in various
later versions of upstream in potentially different ways due to other
code changes:

1) Upon server [-46]  the [-46] are used as FQDN for later resolving
   which does not work.  Make sure we always pass the name (or IP there).

2) The intermediate file to carry the information to the child process
   does not know about -4/-6 restrictions, so that a dual-stacked host
   could resolve to an IPv6 address but that might be unreachable (see
   r223626) leading to no working synchronization ignoring a IPv4 record.
   Thus alter the intermediate format to also pass the address family
   (AF_UNSPEC (default), AF_INET or AF_INET6) to the child process
   depending on -4 or -6.

3) Make the child process to parse the new intermediate file format and
   save the address family for getaddrinfo() hints flags.

4) Change child to always reload resolv.conf calling res_init() before
   trying to resolve names.  This will pick up resolv.conf changes or
   new resolv.confs should they have not existed or been empty or
   unusable on ntp startup.  This fix is more conditional in upstream
   versions but given FreeBSD has res_init there is no need for the
   configure logic as well.

Approved by:	roberto
Sponsored by:	Sandvine Incorporated
MFC after:	9 days
---
 contrib/ntp/ntpd/ntp_config.c | 13 +++++++------
 contrib/ntp/ntpd/ntp_intres.c | 43 +++++++++++++++++++++++++++++--------------
 2 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/contrib/ntp/ntpd/ntp_config.c b/contrib/ntp/ntpd/ntp_config.c
index beb4c48..99af999 100644
--- a/contrib/ntp/ntpd/ntp_config.c
+++ b/contrib/ntp/ntpd/ntp_config.c
@@ -414,7 +414,7 @@ enum gnn_type {
 static	int getnetnum P((const char *, struct sockaddr_storage *, int,
 			 enum gnn_type));
 static	void save_resolve P((char *, int, int, int, int, u_int, int,
-    keyid_t, u_char *));
+    keyid_t, u_char *, u_char));
 static	void do_resolve_internal P((void));
 static	void abort_resolve P((void));
 #if !defined(VMS) && !defined(SYS_WINNT)
@@ -870,9 +870,9 @@ getconfig(
 						stoa(&peeraddr));
 			    }
 			} else if (errflg == -1) {
-				save_resolve(tokens[1], hmode, peerversion,
+				save_resolve(tokens[istart - 1], hmode, peerversion,
 				    minpoll, maxpoll, peerflags, ttl,
-				    peerkey, peerkeystr);
+				    peerkey, peerkeystr, peeraddr.ss_family);
 			}
 			break;
 
@@ -2325,7 +2325,8 @@ save_resolve(
 	u_int flags,
 	int ttl,
 	keyid_t keyid,
-	u_char *keystr
+	u_char *keystr,
+	u_char peeraf
 	)
 {
 #ifndef SYS_VXWORKS
@@ -2365,11 +2366,11 @@ save_resolve(
 	}
 #endif
 
-	(void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name,
+	(void)fprintf(res_fp, "%s %u %d %d %d %d %d %d %u %s\n", name, peeraf,
 	    mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
 #ifdef DEBUG
 	if (debug > 1)
-		printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode,
+		printf("config: %s %u %d %d %d %d %x %d %u %s\n", name, peeraf, mode,
 		    version, minpoll, maxpoll, flags, ttl, keyid, keystr);
 #endif
 
diff --git a/contrib/ntp/ntpd/ntp_intres.c b/contrib/ntp/ntpd/ntp_intres.c
index 5facc85..e18888f 100644
--- a/contrib/ntp/ntpd/ntp_intres.c
+++ b/contrib/ntp/ntpd/ntp_intres.c
@@ -29,6 +29,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 /**/
@@ -111,15 +112,16 @@ static	int resolve_value;	/* next value of resolve timer */
  * is supposed to consist of entries in the following order
  */
 #define	TOK_HOSTNAME	0
-#define	TOK_HMODE	1
-#define	TOK_VERSION	2
-#define TOK_MINPOLL	3
-#define TOK_MAXPOLL	4
-#define	TOK_FLAGS	5
-#define TOK_TTL		6
-#define	TOK_KEYID	7
-#define TOK_KEYSTR	8
-#define	NUMTOK		9
+#define	TOK_PEERAF	1
+#define	TOK_HMODE	2
+#define	TOK_VERSION	3
+#define TOK_MINPOLL	4
+#define TOK_MAXPOLL	5
+#define	TOK_FLAGS	6
+#define TOK_TTL		7
+#define	TOK_KEYID	8
+#define TOK_KEYSTR	9
+#define	NUMTOK		10
 
 #define	MAXLINESIZE	512
 
@@ -140,7 +142,7 @@ char *req_file;		/* name of the file with configuration info */
 static	void	checkparent	P((void));
 static	void	removeentry	P((struct conf_entry *));
 static	void	addentry	P((char *, int, int, int, int, u_int,
-				   int, keyid_t, char *));
+				   int, keyid_t, char *, u_char));
 static	int	findhostaddr	P((struct conf_entry *));
 static	void	openntp		P((void));
 static	int	request		P((struct conf_peer *));
@@ -397,7 +399,8 @@ addentry(
 	u_int flags,
 	int ttl,
 	keyid_t keyid,
-	char *keystr
+	char *keystr,
+	u_char peeraf
 	)
 {
 	register char *cp;
@@ -407,7 +410,7 @@ addentry(
 #ifdef DEBUG
 	if (debug > 1)
 		msyslog(LOG_INFO, 
-		    "intres: <%s> %d %d %d %d %x %d %x %s\n", name,
+		    "intres: <%s> %u %d %d %d %d %x %d %x %s\n", name, peeraf,
 		    mode, version, minpoll, maxpoll, flags, ttl, keyid,
 		    keystr);
 #endif
@@ -422,6 +425,7 @@ addentry(
 	ce->ce_peeraddr6 = in6addr_any;
 #endif
 	ANYSOCK(&ce->peer_store);
+	ce->peer_store.ss_family = peeraf;	/* Save AF for getaddrinfo hints. */
 	ce->ce_hmode = (u_char)mode;
 	ce->ce_version = (u_char)version;
 	ce->ce_minpoll = (u_char)minpoll;
@@ -482,7 +486,8 @@ findhostaddr(
 			entry->ce_name));
 
 		memset(&hints, 0, sizeof(hints));
-		hints.ai_family = AF_UNSPEC;
+		hints.ai_family = entry->peer_store.ss_family;
+		hints.ai_socktype = SOCK_DGRAM;
 		/*
 		 * If the IPv6 stack is not available look only for IPv4 addresses
 		 */
@@ -1051,6 +1056,13 @@ readconf(
 			}
 		}
 
+		if (intval[TOK_PEERAF] != AF_UNSPEC && intval[TOK_PEERAF] !=
+		    AF_INET && intval[TOK_PEERAF] != AF_INET6) {
+			msyslog(LOG_ERR, "invalid peer address family (%u) in "
+			    "file %s", intval[TOK_PEERAF], name);
+			exit(1);
+		}
+
 		if (intval[TOK_HMODE] != MODE_ACTIVE &&
 		    intval[TOK_HMODE] != MODE_CLIENT &&
 		    intval[TOK_HMODE] != MODE_BROADCAST) {
@@ -1107,7 +1119,7 @@ readconf(
 		addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
 			 (int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
 			 (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
-			 intval[TOK_KEYID], token[TOK_KEYSTR]);
+			 intval[TOK_KEYID], token[TOK_KEYSTR], (u_char)intval[TOK_PEERAF]);
 	}
 }
 
@@ -1129,6 +1141,9 @@ doconfigure(
 			    dores ? "with" : "without" );
 #endif
 
+	if (dores)         /* Reload /etc/resolv.conf - bug 1226 */
+		res_init();
+
 	ce = confentries;
 	while (ce != NULL) {
 #ifdef DEBUG
-- 
cgit v1.1


From 624e7334676946983cce00d4d4d517038a630635 Mon Sep 17 00:00:00 2001
From: jonathan 
Date: Wed, 29 Jun 2011 13:03:05 +0000
Subject: We may split today's CAPABILITIES into CAPABILITY_MODE (which has to
 do with global namespaces) and CAPABILITIES (which has to do with
 constraining file descriptors). Just in case, and because it's a better name
 anyway, let's move CAPABILITIES out of the way.

Also, change opt_capabilities.h to opt_capsicum.h; for now, this will
only hold CAPABILITY_MODE, but it will probably also hold the new
CAPABILITIES (implying constrained file descriptors) in the future.

Approved by: rwatson
Sponsored by: Google UK Ltd
---
 sys/amd64/amd64/sys_machdep.c | 4 ++--
 sys/arm/arm/sys_machdep.c     | 4 ++--
 sys/conf/NOTES                | 2 +-
 sys/conf/options              | 2 +-
 sys/i386/i386/sys_machdep.c   | 4 ++--
 sys/kern/subr_trap.c          | 4 ++--
 sys/kern/sys_capability.c     | 8 ++++----
 7 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index fa895f3..beb248c 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -33,7 +33,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
-#include "opt_capabilities.h"
+#include "opt_capsicum.h"
 
 #include 
 #include 
@@ -180,7 +180,7 @@ sysarch(td, uap)
 	uint64_t a64base;
 	struct i386_ioperm_args iargs;
 
-#ifdef CAPABILITIES
+#ifdef CAPABILITY_MODE
 	/*
 	 * Whitelist of operations which are safe enough for capability mode.
 	 */
diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c
index 89e5227..52545d8 100644
--- a/sys/arm/arm/sys_machdep.c
+++ b/sys/arm/arm/sys_machdep.c
@@ -36,7 +36,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
-#include "opt_capabilities.h"
+#include "opt_capsicum.h"
 
 #include 
 #include 
@@ -107,7 +107,7 @@ sysarch(td, uap)
 {
 	int error;
 
-#ifdef CAPABILITIES
+#ifdef CAPABILITY_MODE
 	/*
 	 * Whitelist of operations which are safe enough for capability mode.
 	 */
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index b84d0c5..835c30b 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1162,7 +1162,7 @@ options 	MAC_STUB
 options 	MAC_TEST
 
 # Support for Capsicum
-options 	CAPABILITIES
+options 	CAPABILITY_MODE
 
 
 #####################################################################
diff --git a/sys/conf/options b/sys/conf/options
index 1ce30b1..35c0dfc 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -63,7 +63,7 @@ SYSCTL_DEBUG	opt_sysctl.h
 ADAPTIVE_LOCKMGRS
 ALQ
 AUDIT		opt_global.h
-CAPABILITIES	opt_capabilities.h
+CAPABILITY_MODE	opt_capsicum.h
 CODA_COMPAT_5	opt_coda.h
 COMPAT_43	opt_compat.h
 COMPAT_43TTY	opt_compat.h
diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c
index 6a761bf..e7b0828 100644
--- a/sys/i386/i386/sys_machdep.c
+++ b/sys/i386/i386/sys_machdep.c
@@ -32,7 +32,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
-#include "opt_capabilities.h"
+#include "opt_capsicum.h"
 #include "opt_kstack_pages.h"
 
 #include 
@@ -111,7 +111,7 @@ sysarch(td, uap)
 
 	AUDIT_ARG_CMD(uap->op);
 
-#ifdef CAPABILITIES
+#ifdef CAPABILITY_MODE
 	/*
 	 * Whitelist of operations which are safe enough for capability mode.
 	 */
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 0113d7b..3527ed1 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -44,7 +44,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
-#include "opt_capabilities.h"
+#include "opt_capsicum.h"
 #include "opt_ktrace.h"
 #include "opt_kdtrace.h"
 #include "opt_sched.h"
@@ -313,7 +313,7 @@ syscallenter(struct thread *td, struct syscall_args *sa)
 				goto retval;
 		}
 
-#ifdef CAPABILITIES
+#ifdef CAPABILITY_MODE
 		/*
 		 * In capability mode, we only allow access to system calls
 		 * flagged with SYF_CAPENABLED.
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index c6d9826..a19e881 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -36,7 +36,7 @@
  *
  */
 
-#include "opt_capabilities.h"
+#include "opt_capsicum.h"
 
 #include 
 __FBSDID("$FreeBSD$");
@@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
 #include 
 #include 
 
-#ifdef CAPABILITIES
+#ifdef CAPABILITY_MODE
 
 FEATURE(security_capabilities, "Capsicum Capability Mode");
 
@@ -99,7 +99,7 @@ cap_getmode(struct thread *td, struct cap_getmode_args *uap)
 	return (copyout(&i, uap->modep, sizeof(i)));
 }
 
-#else /* !CAPABILITIES */
+#else /* !CAPABILITY_MODE */
 
 int
 cap_enter(struct thread *td, struct cap_enter_args *uap)
@@ -115,4 +115,4 @@ cap_getmode(struct thread *td, struct cap_getmode_args *uap)
 	return (ENOSYS);
 }
 
-#endif /* CAPABILITIES */
+#endif /* CAPABILITY_MODE */
-- 
cgit v1.1


From 4a4ec8668222820c3a449bd2249c40074c542416 Mon Sep 17 00:00:00 2001
From: bz 
Date: Wed, 29 Jun 2011 13:12:15 +0000
Subject: Clarify that we broke pfsync(4) backward compat with the pf commit
 r223637.

Suggested by:	Anton Yuzhaninov (citrin citrin.ru)
---
 UPDATING | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/UPDATING b/UPDATING
index 985e04e..7df65a3 100644
--- a/UPDATING
+++ b/UPDATING
@@ -25,6 +25,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
 20110628:
 	The packet filter (pf) code has been updated to OpenBSD 4.5.
 	You need to update userland tools to be in sync with kernel.
+	This update breaks backward compatibility with earlier pfsync(4)
+	versions.  Care must be taken when updating redundant firewall setups.
 
 20110608:
 	The following sysctls and tunables are retired on x86 platforms:
-- 
cgit v1.1


From af8134caea44022a9779218bf51c2d5bc8f2572e Mon Sep 17 00:00:00 2001
From: adrian 
Date: Wed, 29 Jun 2011 13:21:52 +0000
Subject: Fix a corner case in STA beacon processing when a CSA is received but
 the AP doesn't transmit beacons.

If the AP requests a CSA (ie, a channel switch) and then enters CAC
(channel availability check) for 60 seconds, it doesn't send beacons
and it just listens for radar events (and other things which we don't
do yet.)

Now, ath_newstate() was not resetting the beacon timer config on
a transition to the RUN state when in STA mode - it was setting
sc_syncbeacon, which simply updates the beacon config from the
contents of the next received beacon.

This means the STA never generates beacon miss events.

If the AP goes into CAC for 60 seconds and recovers, the STA will
happily receive the first beacon and reconfigure timers.
But if it gets a radar event after that, it'll change channel
again, not notify the station that it's changed channel..
and since the station is happily waiting for the first beacon
to configure the beacon timer details from, it won't ever
generate a beacon miss interrupt and it'll sit there forever
(or until the AP appears on that channel once again.)

This change forces the last known beacon timer config to be
written to hardware on a transition from CSA->RUN in STA mode.
This forces bmiss events to occur and the STA will eventually
(after a handful of beacon miss events) begin scanning for
another access point.
---
 sys/dev/ath/if_ath.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 9c534c8..35592d9 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -4693,6 +4693,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 	struct ieee80211_node *ni = NULL;
 	int i, error, stamode;
 	u_int32_t rfilt;
+	int csa_run_transition = 0;
 	static const HAL_LED_STATE leds[] = {
 	    HAL_LED_INIT,	/* IEEE80211_S_INIT */
 	    HAL_LED_SCAN,	/* IEEE80211_S_SCAN */
@@ -4708,6 +4709,9 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 		ieee80211_state_name[vap->iv_state],
 		ieee80211_state_name[nstate]);
 
+	if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN)
+		csa_run_transition = 1;
+
 	callout_drain(&sc->sc_cal_ch);
 	ath_hal_setledstate(ah, leds[nstate]);	/* set LED */
 
@@ -4814,8 +4818,14 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
 			 * Defer beacon timer configuration to the next
 			 * beacon frame so we have a current TSF to use
 			 * (any TSF collected when scanning is likely old).
+			 * However if it's due to a CSA -> RUN transition,
+			 * force a beacon update so we pick up a lack of
+			 * beacons from an AP in CAC and thus force a
+			 * scan.
 			 */
 			sc->sc_syncbeacon = 1;
+			if (csa_run_transition)
+				ath_beacon_config(sc, vap);
 			break;
 		case IEEE80211_M_MONITOR:
 			/*
-- 
cgit v1.1


From 0a17043d52ecf221ee895a37da0fb4cf6fa8582f Mon Sep 17 00:00:00 2001
From: hselasky 
Date: Wed, 29 Jun 2011 14:47:20 +0000
Subject: Add support for a MosChip PCI express serial port adapter.

MFC after:	1 week
---
 sys/dev/uart/uart_bus_pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c
index 48a134b..c479022 100644
--- a/sys/dev/uart/uart_bus_pci.c
+++ b/sys/dev/uart/uart_bus_pci.c
@@ -113,6 +113,8 @@ static struct pci_id pci_ns8250_ids[] = {
 { 0x9710, 0x9820, 0x1000, 1, "NetMos NM9820 Serial Port", 0x10 },
 { 0x9710, 0x9835, 0x1000, 1, "NetMos NM9835 Serial Port", 0x10 },
 { 0x9710, 0x9865, 0xa000, 0x1000, "NetMos NM9865 Serial Port", 0x10 },
+{ 0x9710, 0x9900, 0xa000, 0x1000,
+	"MosChip MCS9900 PCIe to Peripheral Controller", 0x10 },
 { 0x9710, 0x9901, 0xa000, 0x1000,
 	"MosChip MCS9901 PCIe to Peripheral Controller", 0x10 },
 { 0xdeaf, 0x9051, 0xffff, 0, "Middle Digital PC Weasel Serial Port", 0x10 },
-- 
cgit v1.1


From 5d59c4c1dfb136edaf00a29c6fcedcc2a22ed244 Mon Sep 17 00:00:00 2001
From: gber 
Date: Wed, 29 Jun 2011 15:17:29 +0000
Subject: Set proper root device name when legacy NFS client is compiled into
 kernel.

Approved by:     cognet (mentor)
---
 sys/nfs/bootp_subr.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c
index ca90089..bd4a826 100644
--- a/sys/nfs/bootp_subr.c
+++ b/sys/nfs/bootp_subr.c
@@ -44,6 +44,7 @@
 __FBSDID("$FreeBSD$");
 
 #include "opt_bootp.h"
+#include "opt_nfs.h"
 
 #include 
 #include 
@@ -1699,6 +1700,9 @@ bootpc_init(void)
 	}
 
 	rootdevnames[0] = "nfs:";
+#ifdef NFSCLIENT
+	rootdevnames[1] = "oldnfs:";
+#endif
 	mountopts(&nd->root_args, NULL);
 
 	for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next)
-- 
cgit v1.1


From 7b0555e88a9f208857e299f3e8380d8c8f67119b Mon Sep 17 00:00:00 2001
From: jhb 
Date: Wed, 29 Jun 2011 16:20:52 +0000
Subject: - Add read-only sysctls for all of the tunables supported by the igb
 and   em drivers. - Make the per-instance 'enable_aim' sysctl truly
 per-instance by having it   change a per-instance variable (which is used to
 control AIM) rather   than having all of the per-instance sysctls operate on
 a single global   variable.

Reviewed by:	jfv (earlier version)
MFC after:	1 week
---
 sys/dev/e1000/if_em.c  | 29 +++++++++++++++++++++++++++++
 sys/dev/e1000/if_igb.c | 28 +++++++++++++++++++++++-----
 sys/dev/e1000/if_igb.h |  1 +
 3 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 156f8b2..4d8ba65 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -330,42 +330,71 @@ MODULE_DEPEND(em, ether, 1, 1, 1);
 #define CSUM_TSO	0
 #endif
 
+SYSCTL_NODE(_hw, OID_AUTO, em, CTLFLAG_RD, 0, "EM driver parameters");
+
 static int em_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV);
 static int em_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR);
 TUNABLE_INT("hw.em.tx_int_delay", &em_tx_int_delay_dflt);
 TUNABLE_INT("hw.em.rx_int_delay", &em_rx_int_delay_dflt);
+SYSCTL_INT(_hw_em, OID_AUTO, tx_int_delay, CTLFLAG_RDTUN, &em_tx_int_delay_dflt,
+    0, "Default transmit interrupt delay in usecs");
+SYSCTL_INT(_hw_em, OID_AUTO, rx_int_delay, CTLFLAG_RDTUN, &em_rx_int_delay_dflt,
+    0, "Default receive interrupt delay in usecs");
 
 static int em_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV);
 static int em_rx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_RADV);
 TUNABLE_INT("hw.em.tx_abs_int_delay", &em_tx_abs_int_delay_dflt);
 TUNABLE_INT("hw.em.rx_abs_int_delay", &em_rx_abs_int_delay_dflt);
+SYSCTL_INT(_hw_em, OID_AUTO, tx_abs_int_delay, CTLFLAG_RDTUN,
+    &em_tx_abs_int_delay_dflt, 0,
+    "Default transmit interrupt delay limit in usecs");
+SYSCTL_INT(_hw_em, OID_AUTO, rx_abs_int_delay, CTLFLAG_RDTUN,
+    &em_rx_abs_int_delay_dflt, 0,
+    "Default receive interrupt delay limit in usecs");
 
 static int em_rxd = EM_DEFAULT_RXD;
 static int em_txd = EM_DEFAULT_TXD;
 TUNABLE_INT("hw.em.rxd", &em_rxd);
 TUNABLE_INT("hw.em.txd", &em_txd);
+SYSCTL_INT(_hw_em, OID_AUTO, rxd, CTLFLAG_RDTUN, &em_rxd, 0,
+    "Number of receive descriptors per queue");
+SYSCTL_INT(_hw_em, OID_AUTO, txd, CTLFLAG_RDTUN, &em_txd, 0,
+    "Number of transmit descriptors per queue");
 
 static int em_smart_pwr_down = FALSE;
 TUNABLE_INT("hw.em.smart_pwr_down", &em_smart_pwr_down);
+SYSCTL_INT(_hw_em, OID_AUTO, smart_pwr_down, CTLFLAG_RDTUN, &em_smart_pwr_down,
+    0, "Set to true to leave smart power down enabled on newer adapters");
 
 /* Controls whether promiscuous also shows bad packets */
 static int em_debug_sbp = FALSE;
 TUNABLE_INT("hw.em.sbp", &em_debug_sbp);
+SYSCTL_INT(_hw_em, OID_AUTO, sbp, CTLFLAG_RDTUN, &em_debug_sbp, 0,
+    "Show bad packets in promiscuous mode");
 
 static int em_enable_msix = TRUE;
 TUNABLE_INT("hw.em.enable_msix", &em_enable_msix);
+SYSCTL_INT(_hw_em, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &em_enable_msix, 0,
+    "Enable MSI-X interrupts");
 
 /* How many packets rxeof tries to clean at a time */
 static int em_rx_process_limit = 100;
 TUNABLE_INT("hw.em.rx_process_limit", &em_rx_process_limit);
+SYSCTL_INT(_hw_em, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
+    &em_rx_process_limit, 0,
+    "Maximum number of received packets to process at a time, -1 means unlimited");
 
 /* Flow control setting - default to FULL */
 static int em_fc_setting = e1000_fc_full;
 TUNABLE_INT("hw.em.fc_setting", &em_fc_setting);
+SYSCTL_INT(_hw_em, OID_AUTO, fc_setting, CTLFLAG_RDTUN, &em_fc_setting, 0,
+    "Flow control");
 
 /* Energy efficient ethernet - default to OFF */
 static int eee_setting = 0;
 TUNABLE_INT("hw.em.eee_setting", &eee_setting);
+SYSCTL_INT(_hw_em, OID_AUTO, eee_setting, CTLFLAG_RDTUN, &eee_setting, 0,
+    "Enable Energy Efficient Ethernet");
 
 /* Global used in WOL setup with multiport cards */
 static int global_quad_port_a = 0;
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index a1a14b6..972b745 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -300,11 +300,17 @@ MODULE_DEPEND(igb, ether, 1, 1, 1);
  *  Tunable default values.
  *********************************************************************/
 
+SYSCTL_NODE(_hw, OID_AUTO, igb, CTLFLAG_RD, 0, "IGB driver parameters");
+
 /* Descriptor defaults */
 static int igb_rxd = IGB_DEFAULT_RXD;
 static int igb_txd = IGB_DEFAULT_TXD;
 TUNABLE_INT("hw.igb.rxd", &igb_rxd);
 TUNABLE_INT("hw.igb.txd", &igb_txd);
+SYSCTL_INT(_hw_igb, OID_AUTO, rxd, CTLFLAG_RDTUN, &igb_rxd, 0,
+    "Number of receive descriptors per queue");
+SYSCTL_INT(_hw_igb, OID_AUTO, txd, CTLFLAG_RDTUN, &igb_txd, 0,
+    "Number of transmit descriptors per queue");
 
 /*
 ** AIM: Adaptive Interrupt Moderation
@@ -314,6 +320,8 @@ TUNABLE_INT("hw.igb.txd", &igb_txd);
 */
 static int igb_enable_aim = TRUE;
 TUNABLE_INT("hw.igb.enable_aim", &igb_enable_aim);
+SYSCTL_INT(_hw_igb, OID_AUTO, enable_aim, CTLFLAG_RW, &igb_enable_aim, 0,
+    "Enable adaptive interrupt moderation");
 
 /*
  * MSIX should be the default for best performance,
@@ -321,12 +329,16 @@ TUNABLE_INT("hw.igb.enable_aim", &igb_enable_aim);
  */         
 static int igb_enable_msix = 1;
 TUNABLE_INT("hw.igb.enable_msix", &igb_enable_msix);
+SYSCTL_INT(_hw_igb, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &igb_enable_msix, 0,
+    "Enable MSI-X interrupts");
 
 /*
 ** Tuneable Interrupt rate
 */
 static int igb_max_interrupt_rate = 8000;
 TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate);
+SYSCTL_INT(_hw_igb, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
+    &igb_max_interrupt_rate, 0, "Maximum interrupts per second");
 
 /*
 ** Header split causes the packet header to
@@ -338,6 +350,8 @@ TUNABLE_INT("hw.igb.max_interrupt_rate", &igb_max_interrupt_rate);
 */
 static bool igb_header_split = FALSE;
 TUNABLE_INT("hw.igb.hdr_split", &igb_header_split);
+SYSCTL_INT(_hw_igb, OID_AUTO, header_split, CTLFLAG_RDTUN, &igb_header_split, 0,
+    "Enable receive mbuf header split");
 
 /*
 ** This will autoconfigure based on
@@ -345,10 +359,15 @@ TUNABLE_INT("hw.igb.hdr_split", &igb_header_split);
 */
 static int igb_num_queues = 0;
 TUNABLE_INT("hw.igb.num_queues", &igb_num_queues);
+SYSCTL_INT(_hw_igb, OID_AUTO, num_queues, CTLFLAG_RDTUN, &igb_num_queues, 0,
+    "Number of queues to configure, 0 indicates autoconfigure");
 
 /* How many packets rxeof tries to clean at a time */
 static int igb_rx_process_limit = 100;
 TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit);
+SYSCTL_INT(_hw_igb, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
+    &igb_rx_process_limit, 0,
+    "Maximum number of received packets to process at a time, -1 means unlimited");
 
 /*********************************************************************
  *  Device identification routine
@@ -435,10 +454,9 @@ igb_attach(device_t dev)
 	    OID_AUTO, "nvm", CTLTYPE_INT|CTLFLAG_RW, adapter, 0,
 	    igb_sysctl_nvm_info, "I", "NVM Information");
 
-	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-	    OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,
-	    &igb_enable_aim, 1, "Interrupt Moderation");
+	igb_set_sysctl_value(adapter, "enable_aim",
+	    "Interrupt Moderation", &adapter->enable_aim,
+	    igb_enable_aim);
 
 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
@@ -1498,7 +1516,7 @@ igb_msix_que(void *arg)
 
 	more_rx = igb_rxeof(que, adapter->rx_process_limit, NULL);
 
-	if (igb_enable_aim == FALSE)
+	if (adapter->enable_aim == FALSE)
 		goto no_calc;
 	/*
 	** Do Adaptive Interrupt Moderation:
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index f0ab685..80abf6e 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -402,6 +402,7 @@ struct adapter {
 	u16		link_duplex;
 	u32		smartspeed;
 	u32		dmac;
+	int		enable_aim;
 
 	/* Interface queues */
 	struct igb_queue	*queues;
-- 
cgit v1.1


From 21902be08cad124037a2152459b485a54308e5ca Mon Sep 17 00:00:00 2001
From: alc 
Date: Wed, 29 Jun 2011 16:40:41 +0000
Subject: Add a new option, OBJPR_NOTMAPPED, to vm_object_page_remove(). 
 Passing this option to vm_object_page_remove() asserts that the specified
 range of pages is not mapped, or more precisely that none of these pages have
 any managed mappings.  Thus, vm_object_page_remove() need not call
 pmap_remove_all() on the pages.

This change not only saves time by eliminating pointless calls to
pmap_remove_all(), but it also eliminates an inconsistency in the use of
pmap_remove_all() versus related functions, like pmap_remove_write().  It
eliminates harmless but pointless calls to pmap_remove_all() that were being
performed on PG_UNMANAGED pages.

Update all of the existing assertions on pmap_remove_all() to reflect this
change.

Reviewed by:	kib
---
 sys/amd64/amd64/pmap.c    |   4 +-
 sys/arm/arm/pmap.c        |   4 +-
 sys/fs/tmpfs/tmpfs_subr.c |   2 +-
 sys/i386/i386/pmap.c      |   4 +-
 sys/i386/xen/pmap.c       |   4 +-
 sys/ia64/ia64/pmap.c      |   4 +-
 sys/kern/uipc_shm.c       |   2 +-
 sys/kern/vfs_subr.c       |   4 +-
 sys/mips/mips/pmap.c      |   4 +-
 sys/ufs/ffs/ffs_inode.c   |   2 +-
 sys/vm/vm_map.c           |  10 +++-
 sys/vm/vm_object.c        | 123 ++++++++++++++++++++++++----------------------
 sys/vm/vm_object.h        |   9 +++-
 sys/vm/vnode_pager.c      |   2 +-
 14 files changed, 100 insertions(+), 78 deletions(-)

diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 025ca5f..941e85e 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -2847,8 +2847,8 @@ pmap_remove_all(vm_page_t m)
 	vm_offset_t va;
 	vm_page_t free;
 
-	KASSERT((m->flags & PG_FICTITIOUS) == 0,
-	    ("pmap_remove_all: page %p is fictitious", m));
+	KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+	    ("pmap_remove_all: page %p is not managed", m));
 	free = NULL;
 	vm_page_lock_queues();
 	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index cecf363..f684402 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -3120,8 +3120,8 @@ pmap_remove_all(vm_page_t m)
 	pmap_t curpm;
 	int flags = 0;
 
-	KASSERT((m->flags & PG_FICTITIOUS) == 0,
-	    ("pmap_remove_all: page %p is fictitious", m));
+	KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+	    ("pmap_remove_all: page %p is not managed", m));
 	if (TAILQ_EMPTY(&m->md.pv_list))
 		return;
 	vm_page_lock_queues();
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index 5a07a45..e9324cf 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -926,7 +926,7 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize)
 		if (newpages < oldpages) {
 			swap_pager_freespace(uobj, newpages, oldpages -
 			    newpages);
-			vm_object_page_remove(uobj, newpages, 0, FALSE);
+			vm_object_page_remove(uobj, newpages, 0, 0);
 		}
 
 		/*
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 3f9248d..45d19b2 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -2927,8 +2927,8 @@ pmap_remove_all(vm_page_t m)
 	vm_offset_t va;
 	vm_page_t free;
 
-	KASSERT((m->flags & PG_FICTITIOUS) == 0,
-	    ("pmap_remove_all: page %p is fictitious", m));
+	KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+	    ("pmap_remove_all: page %p is not managed", m));
 	free = NULL;
 	vm_page_lock_queues();
 	sched_pin();
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index 3efa4f1..a23ae6d 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -2421,8 +2421,8 @@ pmap_remove_all(vm_page_t m)
 	pt_entry_t *pte, tpte;
 	vm_page_t free;
 
-	KASSERT((m->flags & PG_FICTITIOUS) == 0,
-	    ("pmap_remove_all: page %p is fictitious", m));
+	KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+	    ("pmap_remove_all: page %p is not managed", m));
 	free = NULL;
 	vm_page_lock_queues();
 	sched_pin();
diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c
index 625d0af7..b36f813 100644
--- a/sys/ia64/ia64/pmap.c
+++ b/sys/ia64/ia64/pmap.c
@@ -1424,8 +1424,8 @@ pmap_remove_all(vm_page_t m)
 	pmap_t oldpmap;
 	pv_entry_t pv;
 
-	KASSERT((m->flags & PG_FICTITIOUS) == 0,
-	    ("pmap_remove_all: page %p is fictitious", m));
+	KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+	    ("pmap_remove_all: page %p is not managed", m));
 	vm_page_lock_queues();
 	while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
 		struct ia64_lpte *pte;
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 00496af..cea70c7 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -264,7 +264,7 @@ shm_dotruncate(struct shmfd *shmfd, off_t length)
 		/* Toss in memory pages. */
 		if (nobjsize < object->size)
 			vm_object_page_remove(object, nobjsize, object->size,
-			    FALSE);
+			    0);
 
 		/* Toss pages from swap. */
 		if (object->type == OBJT_SWAP)
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index c5ae83c..934745b 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1190,8 +1190,8 @@ bufobj_invalbuf(struct bufobj *bo, int flags, int slpflag, int slptimeo)
 	 */
 	if (bo->bo_object != NULL && (flags & (V_ALT | V_NORMAL)) == 0) {
 		VM_OBJECT_LOCK(bo->bo_object);
-		vm_object_page_remove(bo->bo_object, 0, 0,
-			(flags & V_SAVE) ? TRUE : FALSE);
+		vm_object_page_remove(bo->bo_object, 0, 0, (flags & V_SAVE) ?
+		    OBJPR_CLEANONLY : 0);
 		VM_OBJECT_UNLOCK(bo->bo_object);
 	}
 
diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c
index f7ea660..1d4d411 100644
--- a/sys/mips/mips/pmap.c
+++ b/sys/mips/mips/pmap.c
@@ -1711,8 +1711,8 @@ pmap_remove_all(vm_page_t m)
 	pv_entry_t pv;
 	pt_entry_t *pte, tpte;
 
-	KASSERT((m->flags & PG_FICTITIOUS) == 0,
-	    ("pmap_remove_all: page %p is fictitious", m));
+	KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+	    ("pmap_remove_all: page %p is not managed", m));
 	vm_page_lock_queues();
 
 	if (m->md.pv_flags & PV_TABLE_REF)
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index a7b43e2..62fa8e0 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -128,7 +128,7 @@ ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
 	if ((object = vp->v_object) == NULL)
 		return;
 	VM_OBJECT_LOCK(object);
-	vm_object_page_remove(object, start, end, FALSE);
+	vm_object_page_remove(object, start, end, 0);
 	VM_OBJECT_UNLOCK(object);
 }
 
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 752354a..31886af 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2708,7 +2708,15 @@ vm_map_entry_delete(vm_map_t map, vm_map_entry_t entry)
 		    ((object->flags & (OBJ_NOSPLIT|OBJ_ONEMAPPING)) == OBJ_ONEMAPPING ||
 		    object == kernel_object || object == kmem_object)) {
 			vm_object_collapse(object);
-			vm_object_page_remove(object, offidxstart, offidxend, FALSE);
+
+			/*
+			 * The option OBJPR_NOTMAPPED can be passed here
+			 * because vm_map_delete() already performed
+			 * pmap_remove() on the only mapping to this range
+			 * of pages. 
+			 */
+			vm_object_page_remove(object, offidxstart, offidxend,
+			    OBJPR_NOTMAPPED);
 			if (object->type == OBJT_SWAP)
 				swap_pager_freespace(object, offidxstart, count);
 			if (offidxend >= object->size &&
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 1a3d398..b5788f5 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -923,6 +923,10 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int pagerflags,
  * We invalidate (remove) all pages from the address space
  * for semantic correctness.
  *
+ * If the backing object is a device object with unmanaged pages, then any
+ * mappings to the specified range of pages must be removed before this
+ * function is called.
+ *
  * Note: certain anonymous maps, such as MAP_NOSYNC maps,
  * may start out with a NULL object.
  */
@@ -978,12 +982,19 @@ vm_object_sync(vm_object_t object, vm_ooffset_t offset, vm_size_t size,
 	}
 	if ((object->type == OBJT_VNODE ||
 	     object->type == OBJT_DEVICE) && invalidate) {
-		boolean_t purge;
-		purge = old_msync || (object->type == OBJT_DEVICE);
-		vm_object_page_remove(object,
-		    OFF_TO_IDX(offset),
-		    OFF_TO_IDX(offset + size + PAGE_MASK),
-		    purge ? FALSE : TRUE);
+		if (object->type == OBJT_DEVICE)
+			/*
+			 * The option OBJPR_NOTMAPPED must be passed here
+			 * because vm_object_page_remove() cannot remove
+			 * unmanaged mappings.
+			 */
+			flags = OBJPR_NOTMAPPED;
+		else if (old_msync)
+			flags = 0;
+		else
+			flags = OBJPR_CLEANONLY;
+		vm_object_page_remove(object, OFF_TO_IDX(offset),
+		    OFF_TO_IDX(offset + size + PAGE_MASK), flags);
 	}
 	VM_OBJECT_UNLOCK(object);
 }
@@ -1754,76 +1765,70 @@ vm_object_collapse(vm_object_t object)
  *	vm_object_page_remove:
  *
  *	For the given object, either frees or invalidates each of the
- *	specified pages.  In general, a page is freed.  However, if a
- *	page is wired for any reason other than the existence of a
- *	managed, wired mapping, then it may be invalidated but not
- *	removed from the object.  Pages are specified by the given
- *	range ["start", "end") and Boolean "clean_only".  As a
- *	special case, if "end" is zero, then the range extends from
- *	"start" to the end of the object.  If "clean_only" is TRUE,
- *	then only the non-dirty pages within the specified range are
- *	affected.
+ *	specified pages.  In general, a page is freed.  However, if a page is
+ *	wired for any reason other than the existence of a managed, wired
+ *	mapping, then it may be invalidated but not removed from the object.
+ *	Pages are specified by the given range ["start", "end") and the option
+ *	OBJPR_CLEANONLY.  As a special case, if "end" is zero, then the range
+ *	extends from "start" to the end of the object.  If the option
+ *	OBJPR_CLEANONLY is specified, then only the non-dirty pages within the
+ *	specified range are affected.  If the option OBJPR_NOTMAPPED is
+ *	specified, then the pages within the specified range must have no
+ *	mappings.  Otherwise, if this option is not specified, any mappings to
+ *	the specified pages are removed before the pages are freed or
+ *	invalidated.
  *
- *	In general, this operation should only be performed on objects
- *	that contain managed pages.  There are two exceptions.  First,
- *	it may be performed on the kernel and kmem objects.  Second,
- *	it may be used by msync(..., MS_INVALIDATE) to invalidate
- *	device-backed pages.  In both of these cases, "clean_only"
- *	must be FALSE.
+ *	In general, this operation should only be performed on objects that
+ *	contain managed pages.  There are, however, two exceptions.  First, it
+ *	is performed on the kernel and kmem objects by vm_map_entry_delete().
+ *	Second, it is used by msync(..., MS_INVALIDATE) to invalidate device-
+ *	backed pages.  In both of these cases, the option OBJPR_CLEANONLY must
+ *	not be specified and the option OBJPR_NOTMAPPED must be specified.
  *
  *	The object must be locked.
  */
 void
 vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end,
-    boolean_t clean_only)
+    int options)
 {
 	vm_page_t p, next;
 	int wirings;
 
 	VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
+	KASSERT((object->type != OBJT_DEVICE && object->type != OBJT_PHYS) ||
+	    (options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED,
+	    ("vm_object_page_remove: illegal options for object %p", object));
 	if (object->resident_page_count == 0)
 		goto skipmemq;
-
-	/*
-	 * Since physically-backed objects do not use managed pages, we can't
-	 * remove pages from the object (we must instead remove the page
-	 * references, and then destroy the object).
-	 */
-	KASSERT(object->type != OBJT_PHYS || object == kernel_object ||
-	    object == kmem_object,
-	    ("attempt to remove pages from a physical object"));
-
 	vm_object_pip_add(object, 1);
 again:
 	p = vm_page_find_least(object, start);
 
 	/*
-	 * Assert: the variable p is either (1) the page with the
-	 * least pindex greater than or equal to the parameter pindex
-	 * or (2) NULL.
+	 * Here, the variable "p" is either (1) the page with the least pindex
+	 * greater than or equal to the parameter "start" or (2) NULL. 
 	 */
-	for (;
-	     p != NULL && (p->pindex < end || end == 0);
-	     p = next) {
+	for (; p != NULL && (p->pindex < end || end == 0); p = next) {
 		next = TAILQ_NEXT(p, listq);
 
 		/*
-		 * If the page is wired for any reason besides the
-		 * existence of managed, wired mappings, then it cannot
-		 * be freed.  For example, fictitious pages, which
-		 * represent device memory, are inherently wired and
-		 * cannot be freed.  They can, however, be invalidated
-		 * if "clean_only" is FALSE.
+		 * If the page is wired for any reason besides the existence
+		 * of managed, wired mappings, then it cannot be freed.  For
+		 * example, fictitious pages, which represent device memory,
+		 * are inherently wired and cannot be freed.  They can,
+		 * however, be invalidated if the option OBJPR_CLEANONLY is
+		 * not specified.
 		 */
 		vm_page_lock(p);
 		if ((wirings = p->wire_count) != 0 &&
 		    (wirings = pmap_page_wired_mappings(p)) != p->wire_count) {
-			/* Fictitious pages do not have managed mappings. */
-			if ((p->flags & PG_FICTITIOUS) == 0)
+			if ((options & OBJPR_NOTMAPPED) == 0) {
 				pmap_remove_all(p);
-			/* Account for removal of managed, wired mappings. */
-			p->wire_count -= wirings;
-			if (!clean_only) {
+				/* Account for removal of wired mappings. */
+				if (wirings != 0)
+					p->wire_count -= wirings;
+			}
+			if ((options & OBJPR_CLEANONLY) == 0) {
 				p->valid = 0;
 				vm_page_undirty(p);
 			}
@@ -1834,17 +1839,20 @@ again:
 			goto again;
 		KASSERT((p->flags & PG_FICTITIOUS) == 0,
 		    ("vm_object_page_remove: page %p is fictitious", p));
-		if (clean_only && p->valid) {
-			pmap_remove_write(p);
+		if ((options & OBJPR_CLEANONLY) != 0 && p->valid != 0) {
+			if ((options & OBJPR_NOTMAPPED) == 0)
+				pmap_remove_write(p);
 			if (p->dirty) {
 				vm_page_unlock(p);
 				continue;
 			}
 		}
-		pmap_remove_all(p);
-		/* Account for removal of managed, wired mappings. */
-		if (wirings != 0)
-			p->wire_count -= wirings;
+		if ((options & OBJPR_NOTMAPPED) == 0) {
+			pmap_remove_all(p);
+			/* Account for removal of wired mappings. */
+			if (wirings != 0)
+				p->wire_count -= wirings;
+		}
 		vm_page_free(p);
 		vm_page_unlock(p);
 	}
@@ -1991,9 +1999,8 @@ vm_object_coalesce(vm_object_t prev_object, vm_ooffset_t prev_offset,
 	 * deallocation.
 	 */
 	if (next_pindex < prev_object->size) {
-		vm_object_page_remove(prev_object,
-				      next_pindex,
-				      next_pindex + next_size, FALSE);
+		vm_object_page_remove(prev_object, next_pindex, next_pindex +
+		    next_size, 0);
 		if (prev_object->type == OBJT_SWAP)
 			swap_pager_freespace(prev_object,
 					     next_pindex, next_size);
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 0f4f47d..a11f144 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -168,6 +168,12 @@ struct vm_object {
 #define OBJPC_INVAL	0x2			/* invalidate */
 #define OBJPC_NOSYNC	0x4			/* skip if PG_NOSYNC */
 
+/*
+ * The following options are supported by vm_object_page_remove().
+ */
+#define	OBJPR_CLEANONLY	0x1		/* Don't remove dirty pages. */
+#define	OBJPR_NOTMAPPED	0x2		/* Don't unmap pages. */
+
 TAILQ_HEAD(object_q, vm_object);
 
 extern struct object_q vm_object_list;	/* list of allocated objects */
@@ -219,7 +225,8 @@ void vm_object_set_writeable_dirty (vm_object_t);
 void vm_object_init (void);
 void vm_object_page_clean(vm_object_t object, vm_ooffset_t start,
     vm_ooffset_t end, int flags);
-void vm_object_page_remove (vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t);
+void vm_object_page_remove(vm_object_t object, vm_pindex_t start,
+    vm_pindex_t end, int options);
 boolean_t vm_object_populate(vm_object_t, vm_pindex_t, vm_pindex_t);
 void vm_object_print(long addr, boolean_t have_addr, long count, char *modif);
 void vm_object_reference (vm_object_t);
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index a8eca20..23ade63 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -387,7 +387,7 @@ vnode_pager_setsize(vp, nsize)
 		 */
 		if (nobjsize < object->size)
 			vm_object_page_remove(object, nobjsize, object->size,
-			    FALSE);
+			    0);
 		/*
 		 * this gets rid of garbage at the end of a page that is now
 		 * only partially backed by the vnode.
-- 
cgit v1.1


From 431ae8d898b487b6197ed7b5dadbffe0349cb6c1 Mon Sep 17 00:00:00 2001
From: yongari 
Date: Wed, 29 Jun 2011 17:32:52 +0000
Subject: Document two known hardware errata which requires manual link
 configuration.

Submitted by:	Aries Lee (arieslee <> jmicron com)
---
 share/man/man4/jme.4 | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/share/man/man4/jme.4 b/share/man/man4/jme.4
index 4220ab5..0bcf652 100644
--- a/share/man/man4/jme.4
+++ b/share/man/man4/jme.4
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 20, 2010
+.Dd June 29, 2011
 .Dt JME 4
 .Os
 .Sh NAME
@@ -178,3 +178,17 @@ address once station address is reprogrammed via eFuse.
 It is highly recommended not to reprogram station address and
 it is responsibility of administrator to store original station
 address into a safe place when station address should be changed.
+.Pp
+There are two known 1000baseT link establishment issues with JMC25x.
+If the full mask revision number of JMC25x controller is less than
+or equal to 4 and link partner enabled IEEE 802.3az Energy Efficient
+Ethernet feature,  the controller would not be able to establish a
+1000baseT link.
+Also if the length of cable is longer than 120 meters, controller
+can not establish a 1000baseT link.
+The known workaround for the issue is to force manual link
+configuration with 100baseTX instead of relying on auto-negotiation.
+The full mask revision number of controller could be checked with
+verbose kernel boot option.
+Use lower nibble of chip revision number to get full mask revision of
+the controller. 
-- 
cgit v1.1


From 323608505b497082bb34811156188d8718eafa5a Mon Sep 17 00:00:00 2001
From: mckusick 
Date: Wed, 29 Jun 2011 22:12:43 +0000
Subject: Handle the FREEDEP case in softdep_sync_buf(). This fix failed to get
 added in -r223325.

Submitted by:	Peter Holm
---
 sys/ufs/ffs/ffs_softdep.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index a10104d..9af5f67 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -12081,6 +12081,7 @@ top:
 			continue;
 
 		case D_FREEWORK:
+		case D_FREEDEP:
 			continue;
 
 		default:
-- 
cgit v1.1


From fd64a169760fe09529a861f3ff9f8157f18263d3 Mon Sep 17 00:00:00 2001
From: imp 
Date: Thu, 30 Jun 2011 05:20:02 +0000
Subject: Add detection for the Marvel 88E1149R and treat it just like the
 88E1149.

---
 sys/dev/mii/e1000phy.c | 6 +++++-
 sys/dev/mii/miidevs    | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c
index b0d7069..e657592 100644
--- a/sys/dev/mii/e1000phy.c
+++ b/sys/dev/mii/e1000phy.c
@@ -107,6 +107,7 @@ static const struct mii_phydesc e1000phys[] = {
 	MII_PHY_DESC(xxMARVELL, E1116),
 	MII_PHY_DESC(xxMARVELL, E1116R),
 	MII_PHY_DESC(xxMARVELL, E1118),
+	MII_PHY_DESC(xxMARVELL, E1149R),
 	MII_PHY_DESC(xxMARVELL, E3016),
 	MII_PHY_DESC(xxMARVELL, PHYG65G),
 	MII_PHY_END
@@ -147,6 +148,7 @@ e1000phy_attach(device_t dev)
 			sc->mii_flags |= MIIF_HAVEFIBER;
 		break;
 	case MII_MODEL_xxMARVELL_E1149:
+	case MII_MODEL_xxMARVELL_E1149R:
 		/*
 		 * Some 88E1149 PHY's page select is initialized to
 		 * point to other bank instead of copper/fiber bank
@@ -208,6 +210,7 @@ e1000phy_reset(struct mii_softc *sc)
 		case MII_MODEL_xxMARVELL_E1116:
 		case MII_MODEL_xxMARVELL_E1118:
 		case MII_MODEL_xxMARVELL_E1149:
+		case MII_MODEL_xxMARVELL_E1149R:
 		case MII_MODEL_xxMARVELL_PHYG65G:
 			/* Disable energy detect mode. */
 			reg &= ~E1000_SCR_EN_DETECT_MASK;
@@ -240,7 +243,8 @@ e1000phy_reset(struct mii_softc *sc)
 		PHY_WRITE(sc, E1000_SCR, reg);
 
 		if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116 ||
-		    sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1149) {
+		    sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1149 ||
+		    sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1149R) {
 			PHY_WRITE(sc, E1000_EADR, 2);
 			reg = PHY_READ(sc, E1000_SCR);
 			reg |= E1000_SCR_RGMII_POWER_UP;
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index 5274940..1b98542 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -248,6 +248,7 @@ model xxMARVELL E1111		0x000c Marvell 88E1111 Gigabit PHY
 model xxMARVELL E1116		0x0021 Marvell 88E1116 Gigabit PHY
 model xxMARVELL E1116R		0x0024 Marvell 88E1116R Gigabit PHY
 model xxMARVELL E1118		0x0022 Marvell 88E1118 Gigabit PHY
+model xxMARVELL E1149R		0x0025 Marvell 88E1149R Quad Gigabit PHY
 model xxMARVELL E3016		0x0026 Marvell 88E3016 10/100 Fast Ethernet PHY
 model xxMARVELL PHYG65G		0x0027 Marvell PHYG65G Gigabit PHY
 model MARVELL E1000		0x0005 Marvell 88E1000 Gigabit PHY
-- 
cgit v1.1


From 4fe845568de43a3a5da76d77483beffedbafa858 Mon Sep 17 00:00:00 2001
From: jeff 
Date: Thu, 30 Jun 2011 05:28:10 +0000
Subject:  - Handle the JOP_SYNC case as appropriate.

Reported by:	pho
---
 sbin/fsck_ffs/suj.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c
index b4aa679..ec8b5ab 100644
--- a/sbin/fsck_ffs/suj.c
+++ b/sbin/fsck_ffs/suj.c
@@ -2261,6 +2261,7 @@ suj_build(void)
 				blk_build((struct jblkrec *)rec);
 				break;
 			case JOP_TRUNC:
+			case JOP_SYNC:
 				ino_build_trunc((struct jtrncrec *)rec);
 				break;
 			default:
-- 
cgit v1.1


From ced9bcf26f7e7107339e61b56b9ba7ceba6049ac Mon Sep 17 00:00:00 2001
From: pluknet 
Date: Thu, 30 Jun 2011 09:20:26 +0000
Subject: Fix quota(1) output.

- Fix calculation of 1024-byte sized blocks from disk blocks shown when -h
option isn't specified. It was broken with quota64 integration.
- In prthumanval(): limit the size of a buffer passed to humanize_number()
to a width of 5 bytes but allow a shorter length if requested. That's what
users expect.

PR:		bin/150151
Reviewed by:	Kirk McKusick
---
 usr.bin/quota/quota.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/usr.bin/quota/quota.c b/usr.bin/quota/quota.c
index 6cc3517..67d9c5a 100644
--- a/usr.bin/quota/quota.c
+++ b/usr.bin/quota/quota.c
@@ -264,8 +264,11 @@ prthumanval(int len, u_int64_t bytes)
 {
 	char buf[len + 1];
 
-	humanize_number(buf, sizeof(buf), bytes, "", HN_AUTOSCALE,
-	    HN_B | HN_NOSPACE | HN_DECIMAL);
+	/*
+	 * Limit the width to 5 bytes as that is what users expect.
+	 */
+	humanize_number(buf, sizeof(buf) < 5 ? sizeof(buf) : 5, bytes, "",
+	    HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
 
 	(void)printf(" %*s", len, buf);
 }
@@ -352,10 +355,13 @@ showquotas(int type, u_long id, const char *name)
 			prthumanval(7, dbtob(qup->dqblk.dqb_bhardlimit));
 		} else {
 			printf(" %7ju%c %7ju %7ju",
-			    dbtob(1024) * (uintmax_t)qup->dqblk.dqb_curblocks,
+			    (uintmax_t)dbtob(qup->dqblk.dqb_curblocks)
+				/ 1024,
 			    (msgb == NULL) ? ' ' : '*',
-			    dbtob(1024) * (uintmax_t)qup->dqblk.dqb_bsoftlimit,
-			    dbtob(1024) * (uintmax_t)qup->dqblk.dqb_bhardlimit);
+			    (uintmax_t)dbtob(qup->dqblk.dqb_bsoftlimit)
+				/ 1024,
+			    (uintmax_t)dbtob(qup->dqblk.dqb_bhardlimit)
+				/ 1024);
 		}
 		if (msgb != NULL)
 			bgrace = timeprt(qup->dqblk.dqb_btime);
-- 
cgit v1.1


From 8c932faae446ada0bed49a41fbb164c821227122 Mon Sep 17 00:00:00 2001
From: jonathan 
Date: Thu, 30 Jun 2011 10:56:02 +0000
Subject: Add some checks to ensure that Capsicum is behaving correctly, and
 add some more explicit comments about what's going on and what future
 maintainers need to do when e.g. adding a new operation to a sys_machdep.c.

Approved by: mentor(rwatson), re(bz)
---
 sys/amd64/amd64/sys_machdep.c     | 34 ++++++++++++++++++----------------
 sys/arm/arm/sys_machdep.c         | 20 +++++++++++---------
 sys/i386/i386/sys_machdep.c       | 26 ++++++++++++++------------
 sys/kern/imgact_elf.c             | 11 +++++++++++
 sys/kern/kern_exec.c              | 24 ++++++++++++++++++++++++
 sys/kern/uipc_shm.c               | 11 +++++++++++
 sys/kern/uipc_syscalls.c          |  7 +++++++
 sys/sparc64/sparc64/sys_machdep.c | 21 +++++++++++++++++++++
 8 files changed, 117 insertions(+), 37 deletions(-)

diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index beb248c..17eada1 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -182,26 +182,28 @@ sysarch(td, uap)
 
 #ifdef CAPABILITY_MODE
 	/*
-	 * Whitelist of operations which are safe enough for capability mode.
+	 * When adding new operations, add a new case statement here to
+	 * explicitly indicate whether or not the operation is safe to
+	 * perform in capability mode.
 	 */
 	if (IN_CAPABILITY_MODE(td)) {
 		switch (uap->op) {
-			case I386_GET_LDT:
-			case I386_SET_LDT:
-			case I386_GET_IOPERM:
-			case I386_GET_FSBASE:
-			case I386_SET_FSBASE:
-			case I386_GET_GSBASE:
-			case I386_SET_GSBASE:
-			case AMD64_GET_FSBASE:
-			case AMD64_SET_FSBASE:
-			case AMD64_GET_GSBASE:
-			case AMD64_SET_GSBASE:
-				break;
+		case I386_GET_LDT:
+		case I386_SET_LDT:
+		case I386_GET_IOPERM:
+		case I386_GET_FSBASE:
+		case I386_SET_FSBASE:
+		case I386_GET_GSBASE:
+		case I386_SET_GSBASE:
+		case AMD64_GET_FSBASE:
+		case AMD64_SET_FSBASE:
+		case AMD64_GET_GSBASE:
+		case AMD64_SET_GSBASE:
+			break;
 
-			case I386_SET_IOPERM:
-			default:
-				return (ECAPMODE);
+		case I386_SET_IOPERM:
+		default:
+			return (ECAPMODE);
 		}
 	}
 #endif
diff --git a/sys/arm/arm/sys_machdep.c b/sys/arm/arm/sys_machdep.c
index 52545d8..4c3e350 100644
--- a/sys/arm/arm/sys_machdep.c
+++ b/sys/arm/arm/sys_machdep.c
@@ -109,18 +109,20 @@ sysarch(td, uap)
 
 #ifdef CAPABILITY_MODE
 	/*
-	 * Whitelist of operations which are safe enough for capability mode.
+	 * When adding new operations, add a new case statement here to
+	 * explicitly indicate whether or not the operation is safe to
+	 * perform in capability mode.
 	 */
 	if (IN_CAPABILITY_MODE(td)) {
 		switch (uap->op) {
-			case ARM_SYNC_ICACHE:
-			case ARM_DRAIN_WRITEBUF:
-			case ARM_SET_TP:
-			case ARM_GET_TP:
-				break;
-
-			default:
-				return (ECAPMODE);
+		case ARM_SYNC_ICACHE:
+		case ARM_DRAIN_WRITEBUF:
+		case ARM_SET_TP:
+		case ARM_GET_TP:
+			break;
+
+		default:
+			return (ECAPMODE);
 		}
 	}
 #endif
diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c
index e7b0828..8370516 100644
--- a/sys/i386/i386/sys_machdep.c
+++ b/sys/i386/i386/sys_machdep.c
@@ -113,22 +113,24 @@ sysarch(td, uap)
 
 #ifdef CAPABILITY_MODE
 	/*
-	 * Whitelist of operations which are safe enough for capability mode.
+	 * When adding new operations, add a new case statement here to
+	 * explicitly indicate whether or not the operation is safe to
+	 * perform in capability mode.
 	 */
 	if (IN_CAPABILITY_MODE(td)) {
 		switch (uap->op) {
-			case I386_GET_LDT:
-			case I386_SET_LDT:
-			case I386_GET_IOPERM:
-			case I386_GET_FSBASE:
-			case I386_SET_FSBASE:
-			case I386_GET_GSBASE:
-			case I386_SET_GSBASE:
-				break;
+		case I386_GET_LDT:
+		case I386_SET_LDT:
+		case I386_GET_IOPERM:
+		case I386_GET_FSBASE:
+		case I386_SET_FSBASE:
+		case I386_GET_GSBASE:
+		case I386_SET_GSBASE:
+			break;
 
-			case I386_SET_IOPERM:
-			default:
-				return (ECAPMODE);
+		case I386_SET_IOPERM:
+		default:
+			return (ECAPMODE);
 		}
 	}
 #endif
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index b41741a..ad79360 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -31,10 +31,12 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include "opt_capsicum.h"
 #include "opt_compat.h"
 #include "opt_core.h"
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -578,6 +580,15 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
 	u_long base_addr = 0;
 	int vfslocked, error, i, numsegs;
 
+#ifdef CAPABILITY_MODE
+	/*
+	 * XXXJA: This check can go away once we are sufficiently confident
+	 * that the checks in namei() are correct.
+	 */
+	if (IN_CAPABILITY_MODE(curthread))
+		return (ECAPMODE);
+#endif
+
 	tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK);
 	nd = &tempdata->nd;
 	attr = &tempdata->attr;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index c51cc39..f30f89a 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -27,12 +27,14 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include "opt_capsicum.h"
 #include "opt_hwpmc_hooks.h"
 #include "opt_kdtrace.h"
 #include "opt_ktrace.h"
 #include "opt_vm.h"
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -415,6 +417,18 @@ do_execve(td, args, mac_p)
 
 interpret:
 	if (args->fname != NULL) {
+#ifdef CAPABILITY_MODE
+		/*
+		 * While capability mode can't reach this point via direct
+		 * path arguments to execve(), we also don't allow
+		 * interpreters to be used in capability mode (for now).
+		 * Catch indirect lookups and return a permissions error.
+		 */
+		if (IN_CAPABILITY_MODE(td)) {
+			error = ECAPMODE;
+			goto exec_fail;
+		}
+#endif
 		error = namei(&nd);
 		if (error)
 			goto exec_fail;
@@ -631,6 +645,13 @@ interpret:
 	 * Don't honor setuid/setgid if the filesystem prohibits it or if
 	 * the process is being traced.
 	 *
+	 * We disable setuid/setgid/etc in compatibility mode on the basis
+	 * that most setugid applications are not written with that
+	 * environment in mind, and will therefore almost certainly operate
+	 * incorrectly. In principle there's no reason that setugid
+	 * applications might not be useful in capability mode, so we may want
+	 * to reconsider this conservative design choice in the future.
+	 *
 	 * XXXMAC: For the time being, use NOSUID to also prohibit
 	 * transitions on the file system.
 	 */
@@ -646,6 +667,9 @@ interpret:
 #endif
 
 	if (credential_changing &&
+#ifdef CAPABILITY_MODE
+	    ((oldcred->cr_flags & CRED_FLAG_CAPMODE) == 0) &&
+#endif
 	    (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 &&
 	    (p->p_flag & P_TRACED) == 0) {
 		/*
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index cea70c7..0414f12 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -55,7 +55,10 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include "opt_capsicum.h"
+
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -486,6 +489,14 @@ shm_open(struct thread *td, struct shm_open_args *uap)
 	mode_t cmode;
 	int fd, error;
 
+#ifdef CAPABILITY_MODE
+	/*
+	 * shm_open(2) is only allowed for anonymous objects.
+	 */
+	if (IN_CAPABILITY_MODE(td) && (uap->path != SHM_ANON))
+		return (ECAPMODE);
+#endif
+
 	if ((uap->flags & O_ACCMODE) != O_RDONLY &&
 	    (uap->flags & O_ACCMODE) != O_RDWR)
 		return (EINVAL);
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 19aaee0..c434973 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -35,6 +35,7 @@
 #include 
 __FBSDID("$FreeBSD$");
 
+#include "opt_capsicum.h"
 #include "opt_inet.h"
 #include "opt_inet6.h"
 #include "opt_sctp.h"
@@ -43,6 +44,7 @@ __FBSDID("$FreeBSD$");
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -675,6 +677,11 @@ sendit(td, s, mp, flags)
 	struct sockaddr *to;
 	int error;
 
+#ifdef CAPABILITY_MODE
+	if (IN_CAPABILITY_MODE(td) && (mp->msg_name != NULL))
+		return (ECAPMODE);
+#endif
+
 	if (mp->msg_name != NULL) {
 		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
 		if (error) {
diff --git a/sys/sparc64/sparc64/sys_machdep.c b/sys/sparc64/sparc64/sys_machdep.c
index 9ac5fbc..530ff95 100644
--- a/sys/sparc64/sparc64/sys_machdep.c
+++ b/sys/sparc64/sparc64/sys_machdep.c
@@ -26,8 +26,11 @@
  * $FreeBSD$
  */
 
+#include "opt_capsicum.h"
+
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -53,6 +56,24 @@ sysarch(struct thread *td, struct sysarch_args *uap)
 {
 	int error;
 
+#ifdef CAPABILITY_MODE
+	/*
+	 * When adding new operations, add a new case statement here to
+	 * explicitly indicate whether or not the operation is safe to
+	 * perform in capability mode.
+	 */
+	if (IN_CAPABILITY_MODE(td)) {
+		switch (uap->op) {
+		case SPARC_SIGTRAMP_INSTALL:
+		case SPARC_UTRAP_INSTALL:
+			break;
+
+		default:
+			return (ECAPMODE);
+		}
+	}
+#endif
+
 	mtx_lock(&Giant);
 	switch (uap->op) {
 	case SPARC_SIGTRAMP_INSTALL:
-- 
cgit v1.1


From 4d4c5b3285343962855e4ac2e891fc6711595b64 Mon Sep 17 00:00:00 2001
From: jonathan 
Date: Thu, 30 Jun 2011 15:22:49 +0000
Subject: When Capsicum starts creating capabilities to wrap existing file
 descriptors, we will want to allocate a new descriptor without installing it
 in the FD array.

Split falloc() into falloc_noinstall() and finstall(), and rewrite
falloc() to call them with appropriate atomicity.

Approved by: mentor (rwatson), re (bz)
---
 sys/kern/kern_descrip.c | 85 +++++++++++++++++++++++++++++++++----------------
 sys/sys/filedesc.h      |  2 ++
 2 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 180d598..7f32d47 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1561,54 +1561,85 @@ fdavail(struct thread *td, int n)
 int
 falloc(struct thread *td, struct file **resultfp, int *resultfd, int flags)
 {
-	struct proc *p = td->td_proc;
 	struct file *fp;
-	int error, i;
+	int error, fd;
+
+	error = falloc_noinstall(td, &fp);
+	if (error)
+		return (error);		/* no reference held on error */
+
+	error = finstall(td, fp, &fd, flags);
+	if (error) {
+		fdrop(fp, td);		/* one reference (fp only) */
+		return (error);
+	}
+
+	if (resultfp != NULL)
+		*resultfp = fp;		/* copy out result */
+	else
+		fdrop(fp, td);		/* release local reference */
+
+	if (resultfd != NULL)
+		*resultfd = fd;
+
+	return (0);
+}
+
+/*
+ * Create a new open file structure without allocating a file descriptor.
+ */
+int
+falloc_noinstall(struct thread *td, struct file **resultfp)
+{
+	struct file *fp;
 	int maxuserfiles = maxfiles - (maxfiles / 20);
 	static struct timeval lastfail;
 	static int curfail;
 
-	fp = uma_zalloc(file_zone, M_WAITOK | M_ZERO);
+	KASSERT(resultfp != NULL, ("%s: resultfp == NULL", __func__));
+
 	if ((openfiles >= maxuserfiles &&
 	    priv_check(td, PRIV_MAXFILES) != 0) ||
 	    openfiles >= maxfiles) {
 		if (ppsratecheck(&lastfail, &curfail, 1)) {
-			printf("kern.maxfiles limit exceeded by uid %i, please see tuning(7).\n",
-				td->td_ucred->cr_ruid);
+			printf("kern.maxfiles limit exceeded by uid %i, "
+			    "please see tuning(7).\n", td->td_ucred->cr_ruid);
 		}
-		uma_zfree(file_zone, fp);
 		return (ENFILE);
 	}
 	atomic_add_int(&openfiles, 1);
-
-	/*
-	 * If the process has file descriptor zero open, add the new file
-	 * descriptor to the list of open files at that point, otherwise
-	 * put it at the front of the list of open files.
-	 */
+	fp = uma_zalloc(file_zone, M_WAITOK | M_ZERO);
 	refcount_init(&fp->f_count, 1);
-	if (resultfp)
-		fhold(fp);
 	fp->f_cred = crhold(td->td_ucred);
 	fp->f_ops = &badfileops;
 	fp->f_data = NULL;
 	fp->f_vnode = NULL;
-	FILEDESC_XLOCK(p->p_fd);
-	if ((error = fdalloc(td, 0, &i))) {
-		FILEDESC_XUNLOCK(p->p_fd);
-		fdrop(fp, td);
-		if (resultfp)
-			fdrop(fp, td);
+	*resultfp = fp;
+	return (0);
+}
+
+/*
+ * Install a file in a file descriptor table.
+ */
+int
+finstall(struct thread *td, struct file *fp, int *fd, int flags)
+{
+	struct filedesc *fdp = td->td_proc->p_fd;
+	int error;
+
+	KASSERT(fd != NULL, ("%s: fd == NULL", __func__));
+	KASSERT(fp != NULL, ("%s: fp == NULL", __func__));
+
+	FILEDESC_XLOCK(fdp);
+	if ((error = fdalloc(td, 0, fd))) {
+		FILEDESC_XUNLOCK(fdp);
 		return (error);
 	}
-	p->p_fd->fd_ofiles[i] = fp;
+	fhold(fp);
+	fdp->fd_ofiles[*fd] = fp;
 	if ((flags & O_CLOEXEC) != 0)
-		p->p_fd->fd_ofileflags[i] |= UF_EXCLOSE;
-	FILEDESC_XUNLOCK(p->p_fd);
-	if (resultfp)
-		*resultfp = fp;
-	if (resultfd)
-		*resultfd = i;
+		fdp->fd_ofileflags[*fd] |= UF_EXCLOSE;
+	FILEDESC_XUNLOCK(fdp);
 	return (0);
 }
 
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 33dddca..2dab741 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -113,6 +113,8 @@ int	dupfdopen(struct thread *td, struct filedesc *fdp, int indx, int dfd,
 	    int mode, int error);
 int	falloc(struct thread *td, struct file **resultfp, int *resultfd,
 	    int flags);
+int	falloc_noinstall(struct thread *td, struct file **resultfp);
+int	finstall(struct thread *td, struct file *fp, int *resultfp, int flags);
 int	fdalloc(struct thread *td, int minfd, int *result);
 int	fdavail(struct thread *td, int n);
 int	fdcheckstd(struct thread *td);
-- 
cgit v1.1


From 2b9b009195e403f0f2fc9bf0d9eeefc2297d94b8 Mon Sep 17 00:00:00 2001
From: dfr 
Date: Thu, 30 Jun 2011 16:08:56 +0000
Subject: Add a version of the FreeBSD bootloader which can run in userland,
 packaged as a shared library. This is intended to be used by BHyVe to load
 FreeBSD kernels into new virtual machines.

---
 sys/boot/Makefile.amd64                    |   1 +
 sys/boot/common/Makefile.inc               |   2 +-
 sys/boot/common/disk.c                     | 788 +++++++++++++++++++++++++++++
 sys/boot/common/disk.h                     |  99 ++++
 sys/boot/common/load_elf.c                 |   2 +-
 sys/boot/common/reloc_elf.c                |   2 +-
 sys/boot/ficl/amd64/sysdep.c               | 101 ++++
 sys/boot/ficl/amd64/sysdep.h               | 434 ++++++++++++++++
 sys/boot/i386/libi386/bioscd.c             |   6 +-
 sys/boot/userboot/Makefile                 |   8 +
 sys/boot/userboot/ficl/Makefile            |  73 +++
 sys/boot/userboot/libstand/Makefile        | 161 ++++++
 sys/boot/userboot/libstand/amd64/_setjmp.S |  93 ++++
 sys/boot/userboot/test/Makefile            |  15 +
 sys/boot/userboot/test/test.c              | 428 ++++++++++++++++
 sys/boot/userboot/userboot.h               | 178 +++++++
 sys/boot/userboot/userboot/Makefile        |  61 +++
 sys/boot/userboot/userboot/autoload.c      |  35 ++
 sys/boot/userboot/userboot/bootinfo.c      | 192 +++++++
 sys/boot/userboot/userboot/bootinfo32.c    | 264 ++++++++++
 sys/boot/userboot/userboot/bootinfo64.c    | 304 +++++++++++
 sys/boot/userboot/userboot/conf.c          |  93 ++++
 sys/boot/userboot/userboot/copy.c          |  74 +++
 sys/boot/userboot/userboot/devicename.c    | 274 ++++++++++
 sys/boot/userboot/userboot/elf32_freebsd.c |  99 ++++
 sys/boot/userboot/userboot/elf64_freebsd.c | 172 +++++++
 sys/boot/userboot/userboot/host.c          | 198 ++++++++
 sys/boot/userboot/userboot/libuserboot.h   |  67 +++
 sys/boot/userboot/userboot/main.c          | 177 +++++++
 sys/boot/userboot/userboot/userboot_cons.c |  86 ++++
 sys/boot/userboot/userboot/userboot_disk.c | 146 ++++++
 sys/boot/userboot/userboot/version         |   4 +
 32 files changed, 4633 insertions(+), 4 deletions(-)
 create mode 100644 sys/boot/common/disk.c
 create mode 100644 sys/boot/common/disk.h
 create mode 100644 sys/boot/ficl/amd64/sysdep.c
 create mode 100644 sys/boot/ficl/amd64/sysdep.h
 create mode 100644 sys/boot/userboot/Makefile
 create mode 100644 sys/boot/userboot/ficl/Makefile
 create mode 100644 sys/boot/userboot/libstand/Makefile
 create mode 100644 sys/boot/userboot/libstand/amd64/_setjmp.S
 create mode 100644 sys/boot/userboot/test/Makefile
 create mode 100644 sys/boot/userboot/test/test.c
 create mode 100644 sys/boot/userboot/userboot.h
 create mode 100644 sys/boot/userboot/userboot/Makefile
 create mode 100644 sys/boot/userboot/userboot/autoload.c
 create mode 100644 sys/boot/userboot/userboot/bootinfo.c
 create mode 100644 sys/boot/userboot/userboot/bootinfo32.c
 create mode 100644 sys/boot/userboot/userboot/bootinfo64.c
 create mode 100644 sys/boot/userboot/userboot/conf.c
 create mode 100644 sys/boot/userboot/userboot/copy.c
 create mode 100644 sys/boot/userboot/userboot/devicename.c
 create mode 100644 sys/boot/userboot/userboot/elf32_freebsd.c
 create mode 100644 sys/boot/userboot/userboot/elf64_freebsd.c
 create mode 100644 sys/boot/userboot/userboot/host.c
 create mode 100644 sys/boot/userboot/userboot/libuserboot.h
 create mode 100644 sys/boot/userboot/userboot/main.c
 create mode 100644 sys/boot/userboot/userboot/userboot_cons.c
 create mode 100644 sys/boot/userboot/userboot/userboot_disk.c
 create mode 100644 sys/boot/userboot/userboot/version

diff --git a/sys/boot/Makefile.amd64 b/sys/boot/Makefile.amd64
index 256201d..b9e1609 100644
--- a/sys/boot/Makefile.amd64
+++ b/sys/boot/Makefile.amd64
@@ -2,3 +2,4 @@
 
 SUBDIR+=		efi
 SUBDIR+=		zfs
+SUBDIR+=		userboot
diff --git a/sys/boot/common/Makefile.inc b/sys/boot/common/Makefile.inc
index be6c3301..ad9535c 100644
--- a/sys/boot/common/Makefile.inc
+++ b/sys/boot/common/Makefile.inc
@@ -1,6 +1,6 @@
 # $FreeBSD$
 
-SRCS+=	boot.c commands.c console.c devopen.c interp.c 
+SRCS+=	boot.c commands.c console.c devopen.c disk.c interp.c 
 SRCS+=	interp_backslash.c interp_parse.c ls.c misc.c 
 SRCS+=	module.c panic.c
 
diff --git a/sys/boot/common/disk.c b/sys/boot/common/disk.c
new file mode 100644
index 0000000..40dbc8a
--- /dev/null
+++ b/sys/boot/common/disk.c
@@ -0,0 +1,788 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+/*
+ * MBR/GPT partitioned disk device handling.
+ *
+ * Ideas and algorithms from:
+ *
+ * - NetBSD libi386/biosdisk.c
+ * - FreeBSD biosboot/disk.c
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+
+#include "disk.h"
+
+#ifdef DISK_DEBUG
+# define DEBUG(fmt, args...)	printf("%s: " fmt "\n" , __func__ , ## args)
+#else
+# define DEBUG(fmt, args...)
+#endif
+
+/*
+ * Search for a slice with the following preferences:
+ *
+ * 1: Active FreeBSD slice
+ * 2: Non-active FreeBSD slice
+ * 3: Active Linux slice
+ * 4: non-active Linux slice
+ * 5: Active FAT/FAT32 slice
+ * 6: non-active FAT/FAT32 slice
+ */
+#define PREF_RAWDISK	0
+#define PREF_FBSD_ACT	1
+#define PREF_FBSD	2
+#define PREF_LINUX_ACT	3
+#define PREF_LINUX	4
+#define PREF_DOS_ACT	5
+#define PREF_DOS	6
+#define PREF_NONE	7
+
+#ifdef LOADER_GPT_SUPPORT
+
+struct gpt_part {
+	int		gp_index;
+	uuid_t		gp_type;
+	uint64_t	gp_start;
+	uint64_t	gp_end;
+};
+
+static uuid_t efi = GPT_ENT_TYPE_EFI;
+static uuid_t freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT;
+static uuid_t freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS;
+static uuid_t freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP;
+static uuid_t freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS;
+static uuid_t ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA;
+
+#endif
+
+/* Given a size in 512 byte sectors, convert it to a human-readable number. */
+static char *
+display_size(uint64_t size)
+{
+	static char buf[80];
+	char unit;
+
+	size /= 2;
+	unit = 'K';
+	if (size >= 10485760000LL) {
+		size /= 1073741824;
+		unit = 'T';
+	} else if (size >= 10240000) {
+		size /= 1048576;
+		unit = 'G';
+	} else if (size >= 10000) {
+		size /= 1024;
+		unit = 'M';
+	}
+	sprintf(buf, "%.6ld%cB", (long)size, unit);
+	return (buf);
+}
+
+static void
+disk_checkextended(struct disk_devdesc *dev,
+    struct dos_partition *slicetab, int slicenum, int *nslicesp)
+{
+	uint8_t			buf[DISK_SECSIZE];
+	struct dos_partition	*dp;
+	uint32_t		base;
+	int			rc, i, start, end;
+
+	dp = &slicetab[slicenum];
+	start = *nslicesp;
+
+	if (dp->dp_size == 0)
+		goto done;
+	if (dp->dp_typ != DOSPTYP_EXT)
+		goto done;
+	rc = dev->d_dev->dv_strategy(dev, F_READ, dp->dp_start, DISK_SECSIZE,
+		(char *) buf, NULL);
+	if (rc)
+		goto done;
+	if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) {
+		DEBUG("no magic in extended table");
+		goto done;
+	}
+	base = dp->dp_start;
+	dp = (struct dos_partition *) &buf[DOSPARTOFF];
+	for (i = 0; i < NDOSPART; i++, dp++) {
+		if (dp->dp_size == 0)
+			continue;
+		if (*nslicesp == NEXTDOSPART)
+			goto done;
+		dp->dp_start += base;
+		bcopy(dp, &slicetab[*nslicesp], sizeof(*dp));
+		(*nslicesp)++;
+	}
+	end = *nslicesp;
+
+	/*
+	 * now, recursively check the slices we just added
+	 */
+	for (i = start; i < end; i++)
+		disk_checkextended(dev, slicetab, i, nslicesp);
+done:
+	return;
+}
+
+static int
+disk_readslicetab(struct disk_devdesc *dev,
+    struct dos_partition **slicetabp, int *nslicesp)
+{
+	struct dos_partition	*slicetab = NULL;
+	int			nslices, i;
+	int			rc;
+	uint8_t			buf[DISK_SECSIZE];
+
+	/*
+	 * Find the slice in the DOS slice table.
+	 */
+	rc = dev->d_dev->dv_strategy(dev, F_READ, 0, DISK_SECSIZE,
+		(char *) buf, NULL);
+	if (rc) {
+		DEBUG("error reading MBR");
+		return (rc);
+	}
+
+	/*
+	 * Check the slice table magic.
+	 */
+	if (buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) {
+		DEBUG("no slice table/MBR (no magic)");
+		return (rc);
+	}
+
+	/*
+	 * copy the partition table, then pick up any extended partitions.
+	 */
+	slicetab = malloc(NEXTDOSPART * sizeof(struct dos_partition));
+	bcopy(buf + DOSPARTOFF, slicetab,
+		sizeof(struct dos_partition) * NDOSPART);
+	nslices = NDOSPART;		/* extended slices start here */
+	for (i = 0; i < NDOSPART; i++)
+		disk_checkextended(dev, slicetab, i, &nslices);
+
+	*slicetabp = slicetab;
+	*nslicesp = nslices;
+	return (0);
+}
+
+/*
+ * Search for the best MBR slice (typically the first FreeBSD slice).
+ */
+static int
+disk_bestslice(struct dos_partition *slicetab, int nslices)
+{
+	struct dos_partition *dp;
+	int pref, preflevel;
+	int i, prefslice;
+
+	prefslice = 0;
+	preflevel = PREF_NONE;
+
+	dp = &slicetab[0];
+	for (i = 0; i < nslices; i++, dp++) {
+		switch (dp->dp_typ) {
+		case DOSPTYP_386BSD:		/* FreeBSD */
+			pref = dp->dp_flag & 0x80 ? PREF_FBSD_ACT : PREF_FBSD;
+			break;
+
+		case DOSPTYP_LINUX:
+			pref = dp->dp_flag & 0x80 ? PREF_LINUX_ACT : PREF_LINUX;
+			break;
+
+		case 0x01:		/* DOS/Windows */
+		case 0x04:
+		case 0x06:
+		case 0x0b:
+		case 0x0c:
+		case 0x0e:
+			pref = dp->dp_flag & 0x80 ? PREF_DOS_ACT : PREF_DOS;
+			break;
+
+		default:
+		        pref = PREF_NONE;
+		}
+		if (pref < preflevel) {
+			preflevel = pref;
+			prefslice = i + 1;
+		}
+	}
+	return (prefslice);
+}
+
+static int
+disk_openmbr(struct disk_devdesc *dev)
+{
+	struct dos_partition	*slicetab = NULL, *dptr;
+	int			nslices, sector, slice;
+	int			rc;
+	uint8_t			buf[DISK_SECSIZE];
+	struct disklabel	*lp;
+
+	/*
+	 * Following calculations attempt to determine the correct value
+	 * for dev->d_offset by looking for the slice and partition specified,
+	 * or searching for reasonable defaults.
+	 */
+	rc = disk_readslicetab(dev, &slicetab, &nslices);
+	if (rc)
+		return (rc);
+
+	/*
+	 * if a slice number was supplied but not found, this is an error.
+	 */
+	if (dev->d_slice > 0) {
+		slice = dev->d_slice - 1;
+		if (slice >= nslices) {
+			DEBUG("slice %d not found", slice);
+			rc = EPART;
+			goto out;
+		}
+	}
+
+	/*
+	 * Check for the historically bogus MBR found on true dedicated disks
+	 */
+	if (slicetab[3].dp_typ == DOSPTYP_386BSD &&
+	    slicetab[3].dp_start == 0 && slicetab[3].dp_size == 50000) {
+		sector = 0;
+		goto unsliced;
+	}
+
+	/*
+	 * Try to auto-detect the best slice; this should always give
+	 * a slice number
+	 */
+	if (dev->d_slice == 0) {
+		slice = disk_bestslice(slicetab, nslices);
+		if (slice == -1) {
+			rc = ENOENT;
+			goto out;
+		}
+		dev->d_slice = slice;
+	}
+
+	/*
+	 * Accept the supplied slice number unequivocally (we may be looking
+	 * at a DOS partition).
+	 * Note: we number 1-4, offsets are 0-3
+	 */
+	dptr = &slicetab[dev->d_slice - 1];
+	sector = dptr->dp_start;
+	DEBUG("slice entry %d at %d, %d sectors",
+		dev->d_slice - 1, sector, dptr->dp_size);
+
+unsliced:
+	/*
+	 * Now we have the slice offset, look for the partition in the
+	 * disklabel if we have a partition to start with.
+	 *
+	 * XXX we might want to check the label checksum.
+	 */
+	if (dev->d_partition < 0) {
+		/* no partition, must be after the slice */
+		DEBUG("opening raw slice");
+		dev->d_offset = sector;
+		rc = 0;
+		goto out;
+	}
+
+	rc = dev->d_dev->dv_strategy(dev, F_READ, sector + LABELSECTOR,
+            DISK_SECSIZE, (char *) buf, NULL);
+	if (rc) {
+		DEBUG("error reading disklabel");
+		goto out;
+	}
+
+	lp = (struct disklabel *) buf;
+
+	if (lp->d_magic != DISKMAGIC) {
+		DEBUG("no disklabel");
+		rc = ENOENT;
+		goto out;
+	}
+	if (dev->d_partition >= lp->d_npartitions) {
+		DEBUG("partition '%c' exceeds partitions in table (a-'%c')",
+		  'a' + dev->d_partition,
+		  'a' + lp->d_npartitions);
+		rc = EPART;
+		goto out;
+	}
+
+	dev->d_offset =
+		lp->d_partitions[dev->d_partition].p_offset -
+		lp->d_partitions[RAW_PART].p_offset +
+		sector;
+	rc = 0;
+
+out:
+	if (slicetab)
+		free(slicetab);
+	return (rc);
+}
+
+/*
+ * Print out each valid partition in the disklabel of a FreeBSD slice.
+ * For size calculations, we assume a 512 byte sector size.
+ */
+static void
+disk_printbsdslice(struct disk_devdesc *dev, daddr_t offset,
+    char *prefix, int verbose)
+{
+	char			line[80];
+	char			buf[DISK_SECSIZE];
+	struct disklabel	*lp;
+	int			i, rc, fstype;
+
+	/* read disklabel */
+	rc = dev->d_dev->dv_strategy(dev, F_READ, offset + LABELSECTOR,
+		DISK_SECSIZE, (char *) buf, NULL);
+	if (rc)
+		return;
+	lp =(struct disklabel *)(&buf[0]);
+	if (lp->d_magic != DISKMAGIC) {
+		sprintf(line, "%s: FFS  bad disklabel\n", prefix);
+		pager_output(line);
+		return;
+	}
+
+	/* Print partitions */
+	for (i = 0; i < lp->d_npartitions; i++) {
+		/*
+		 * For each partition, make sure we know what type of fs it
+		 * is.  If not, then skip it.
+		 */
+		fstype = lp->d_partitions[i].p_fstype;
+		if (fstype != FS_BSDFFS &&
+		    fstype != FS_SWAP &&
+		    fstype != FS_VINUM)
+			continue;
+
+		/* Only print out statistics in verbose mode */
+		if (verbose)
+			sprintf(line, "  %s%c: %s %s (%d - %d)\n",
+				prefix, 'a' + i,
+			    (fstype == FS_SWAP) ? "swap " :
+			    (fstype == FS_VINUM) ? "vinum" :
+			    "FFS  ",
+			    display_size(lp->d_partitions[i].p_size),
+			    lp->d_partitions[i].p_offset,
+			    (lp->d_partitions[i].p_offset
+			     + lp->d_partitions[i].p_size));
+		else
+			sprintf(line, "  %s%c: %s\n", prefix, 'a' + i,
+			    (fstype == FS_SWAP) ? "swap" :
+			    (fstype == FS_VINUM) ? "vinum" :
+			    "FFS");
+		pager_output(line);
+	}
+}
+
+static void
+disk_printslice(struct disk_devdesc *dev, int slice,
+    struct dos_partition *dp, char *prefix, int verbose)
+{
+	char stats[80];
+	char line[80];
+
+	if (verbose)
+		sprintf(stats, " %s (%d - %d)", display_size(dp->dp_size),
+		    dp->dp_start, dp->dp_start + dp->dp_size);
+	else
+		stats[0] = '\0';
+
+	switch (dp->dp_typ) {
+	case DOSPTYP_386BSD:
+		disk_printbsdslice(dev, (daddr_t)dp->dp_start,
+		     prefix, verbose);
+		return;
+	case DOSPTYP_LINSWP:
+		sprintf(line, "%s: Linux swap%s\n", prefix, stats);
+		break;
+	case DOSPTYP_LINUX:
+		/*
+		 * XXX
+		 * read the superblock to confirm this is an ext2fs partition?
+		 */
+		sprintf(line, "%s: ext2fs%s\n", prefix, stats);
+		break;
+	case 0x00:				/* unused partition */
+	case DOSPTYP_EXT:
+		return;
+	case 0x01:
+		sprintf(line, "%s: FAT-12%s\n", prefix, stats);
+		break;
+	case 0x04:
+	case 0x06:
+	case 0x0e:
+		sprintf(line, "%s: FAT-16%s\n", prefix, stats);
+		break;
+	case 0x07:
+		sprintf(line, "%s: NTFS/HPFS%s\n", prefix, stats);
+		break;
+	case 0x0b:
+	case 0x0c:
+		sprintf(line, "%s: FAT-32%s\n", prefix, stats);
+		break;
+	default:
+		sprintf(line, "%s: Unknown fs: 0x%x %s\n", prefix, dp->dp_typ,
+		    stats);
+	}
+	pager_output(line);
+}
+
+int
+disk_printmbr(struct disk_devdesc *dev, char *prefix, int verbose)
+{
+	struct dos_partition	*slicetab;
+	int			nslices, i;
+	int			rc;
+	char			line[80];
+
+	rc = disk_readslicetab(dev, &slicetab, &nslices);
+	if (rc)
+		return (rc);
+	for (i = 0; i < nslices; i++) {
+		sprintf(line, "%ss%d", prefix, i + 1);
+		disk_printslice(dev, i, &slicetab[i], line, verbose);
+	}
+	free(slicetab);
+	return (0);
+}
+
+#ifdef LOADER_GPT_SUPPORT
+
+static int
+disk_readgpt(struct disk_devdesc *dev, struct gpt_part **gptp, int *ngptp)
+{
+	struct dos_partition	*dp;
+	struct gpt_hdr		*hdr;
+	struct gpt_ent		*ent;
+	struct gpt_part		*gptab = NULL;
+	int			entries_per_sec, rc, i, part;
+	daddr_t			lba, elba;
+	uint8_t			gpt[DISK_SECSIZE], tbl[DISK_SECSIZE];
+
+	/*
+	 * Following calculations attempt to determine the correct value
+	 * for dev->d_offset by looking for the slice and partition specified,
+	 * or searching for reasonable defaults.
+	 */
+	rc = 0;
+
+	/* First, read the MBR and see if we have a PMBR. */
+	rc = dev->d_dev->dv_strategy(dev, F_READ, 0, DISK_SECSIZE,
+		(char *) tbl, NULL);
+	if (rc) {
+		DEBUG("error reading MBR");
+		return (EIO);
+	}
+
+	/* Check the slice table magic. */
+	if (tbl[0x1fe] != 0x55 || tbl[0x1ff] != 0xaa)
+		return (ENXIO);
+
+	/* Check for GPT slice. */
+	part = 0;
+	dp = (struct dos_partition *)(tbl + DOSPARTOFF);
+	for (i = 0; i < NDOSPART; i++) {
+		if (dp[i].dp_typ == 0xee)
+			part++;
+		else if ((part != 1) && (dp[i].dp_typ != 0x00))
+			return (EINVAL);
+	}
+	if (part != 1)
+		return (EINVAL);
+
+	/* Read primary GPT table header. */
+	rc = dev->d_dev->dv_strategy(dev, F_READ, 1, DISK_SECSIZE,
+		(char *) gpt, NULL);
+	if (rc) {
+		DEBUG("error reading GPT header");
+		return (EIO);
+	}
+	hdr = (struct gpt_hdr *)gpt;
+	if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 ||
+	    hdr->hdr_lba_self != 1 || hdr->hdr_revision < 0x00010000 ||
+	    hdr->hdr_entsz < sizeof(*ent) ||
+	    DISK_SECSIZE % hdr->hdr_entsz != 0) {
+		DEBUG("Invalid GPT header\n");
+		return (EINVAL);
+	}
+
+	/* Walk the partition table to count valid partitions. */
+	part = 0;
+	entries_per_sec = DISK_SECSIZE / hdr->hdr_entsz;
+	elba = hdr->hdr_lba_table + hdr->hdr_entries / entries_per_sec;
+	for (lba = hdr->hdr_lba_table; lba < elba; lba++) {
+		rc = dev->d_dev->dv_strategy(dev, F_READ, lba, DISK_SECSIZE,
+			(char *) tbl, NULL);
+		if (rc) {
+			DEBUG("error reading GPT table");
+			return (EIO);
+		}
+		for (i = 0; i < entries_per_sec; i++) {
+			ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz);
+			if (uuid_is_nil(&ent->ent_type, NULL) ||
+			    ent->ent_lba_start == 0 ||
+			    ent->ent_lba_end < ent->ent_lba_start)
+				continue;
+			part++;
+		}
+	}
+
+	/* Save the important information about all the valid partitions. */
+	if (part != 0) {
+		gptab = malloc(part * sizeof(struct gpt_part));
+		part = 0;
+		for (lba = hdr->hdr_lba_table; lba < elba; lba++) {
+			rc = dev->d_dev->dv_strategy(dev, F_READ, lba, DISK_SECSIZE,
+				(char *) tbl, NULL);
+			if (rc) {
+				DEBUG("error reading GPT table");
+				free(gptab);
+				return (EIO);
+			}
+			for (i = 0; i < entries_per_sec; i++) {
+				ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz);
+				if (uuid_is_nil(&ent->ent_type, NULL) ||
+				    ent->ent_lba_start == 0 ||
+				    ent->ent_lba_end < ent->ent_lba_start)
+					continue;
+				gptab[part].gp_index = (lba - hdr->hdr_lba_table) *
+					entries_per_sec + i + 1;
+				gptab[part].gp_type = ent->ent_type;
+				gptab[part].gp_start = ent->ent_lba_start;
+				gptab[part].gp_end = ent->ent_lba_end;
+				part++;
+			}
+		}
+	}
+
+	*gptp = gptab;
+	*ngptp = part;
+	return (0);
+}
+
+static struct gpt_part *
+disk_bestgpt(struct gpt_part *gpt, int ngpt)
+{
+	struct gpt_part *gp, *prefpart;
+	int i, pref, preflevel;
+
+	prefpart = NULL;
+	preflevel = PREF_NONE;
+
+	gp = gpt;
+	for (i = 0; i < ngpt; i++, gp++) {
+		/* Windows. XXX: Also Linux. */
+		if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL))
+			pref = PREF_DOS;
+		/* FreeBSD */
+		else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL) ||
+		         uuid_equal(&gp->gp_type, &freebsd_zfs, NULL))
+			pref = PREF_FBSD;
+		else
+			pref = PREF_NONE;
+		if (pref < preflevel) {
+			preflevel = pref;
+			prefpart = gp;
+		}
+	}
+	return (prefpart);
+}
+
+int
+disk_opengpt(struct disk_devdesc *dev)
+{
+	struct gpt_part		*gpt = NULL, *gp;
+	int			rc, ngpt, i;
+
+	rc = disk_readgpt(dev, &gpt, &ngpt);
+	if (rc)
+		return (rc);
+
+	/* Is this a request for the whole disk? */
+	if (dev->d_slice < 0) {
+		dev->d_offset = 0;
+		rc = 0;
+		goto out;
+	}
+
+	/*
+	 * If a partition number was supplied, then the user is trying to use
+	 * an MBR address rather than a GPT address, so fail.
+	 */
+	if (dev->d_partition != 0xff) {
+		rc = ENOENT;
+		goto out;
+	}
+
+	/* If a slice number was supplied but not found, this is an error. */
+	gp = NULL;
+	if (dev->d_slice > 0) {
+		for (i = 0; i < ngpt; i++) {
+			if (gpt[i].gp_index == dev->d_slice) {
+				gp = &gpt[i];
+				break;
+			}
+		}
+		if (gp == NULL) {
+			DEBUG("partition %d not found", dev->d_slice);
+			rc = ENOENT;
+			goto out;
+		}
+	}
+
+	/* Try to auto-detect the best partition. */
+	if (dev->d_slice == 0) {
+		gp = disk_bestgpt(gpt, ngpt);
+		if (gp == NULL) {
+			rc = ENOENT;
+			goto out;
+		}
+		dev->d_slice = gp->gp_index;
+	}
+
+	dev->d_offset = gp->gp_start;
+	rc = 0;
+
+out:
+	if (gpt)
+		free(gpt);
+	return (rc);
+}
+
+static void
+disk_printgptpart(struct disk_devdesc *dev, struct gpt_part *gp,
+    char *prefix, int verbose)
+{
+	char stats[80];
+	char line[96];
+
+	if (verbose)
+		sprintf(stats, " %s",
+			display_size(gp->gp_end + 1 - gp->gp_start));
+	else
+		stats[0] = '\0';
+
+	if (uuid_equal(&gp->gp_type, &efi, NULL))
+		sprintf(line, "%s: EFI         %s\n", prefix, stats);
+	else if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL))
+		sprintf(line, "%s: FAT/NTFS    %s\n", prefix, stats);
+	else if (uuid_equal(&gp->gp_type, &freebsd_boot, NULL))
+		sprintf(line, "%s: FreeBSD boot%s\n", prefix, stats);
+	else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL))
+		sprintf(line, "%s: FreeBSD UFS %s\n", prefix, stats);
+	else if (uuid_equal(&gp->gp_type, &freebsd_zfs, NULL))
+		sprintf(line, "%s: FreeBSD ZFS %s\n", prefix, stats);
+	else if (uuid_equal(&gp->gp_type, &freebsd_swap, NULL))
+		sprintf(line, "%s: FreeBSD swap%s\n", prefix, stats);
+	else
+		sprintf(line,
+		    "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n",
+		    prefix,
+		    gp->gp_type.time_low, gp->gp_type.time_mid,
+		    gp->gp_type.time_hi_and_version,
+		    gp->gp_type.clock_seq_hi_and_reserved,
+		    gp->gp_type.clock_seq_low,
+		    gp->gp_type.node[0],
+		    gp->gp_type.node[1],
+		    gp->gp_type.node[2],
+		    gp->gp_type.node[3],
+		    gp->gp_type.node[4],
+		    gp->gp_type.node[5],
+		    stats);
+	pager_output(line);
+}
+
+static int
+disk_printgpt(struct disk_devdesc *dev, char *prefix, int verbose)
+{
+	struct gpt_part		*gpt = NULL;
+	int			rc, ngpt, i;
+	char			line[80];
+
+	rc = disk_readgpt(dev, &gpt, &ngpt);
+	if (rc)
+		return (rc);
+	for (i = 0; i < ngpt; i++) {
+		sprintf(line, "%sp%d", prefix, i + 1);
+		disk_printgptpart(dev, &gpt[i], line, verbose);
+	}
+	free(gpt);
+	return (0);
+}
+
+#endif
+
+int
+disk_open(struct disk_devdesc *dev)
+{
+	int rc;
+
+	/*
+	 * While we are reading disk metadata, make sure we do it relative
+	 * to the start of the disk
+	 */
+	dev->d_offset = 0;
+
+#ifdef LOADER_GPT_SUPPORT
+	rc = disk_opengpt(dev);
+	if (rc)
+#endif
+		rc = disk_openmbr(dev);
+
+	return (rc);
+}
+
+void
+disk_print(struct disk_devdesc *dev, char *prefix, int verbose)
+{
+	int			rc;
+
+#ifdef LOADER_GPT_SUPPORT
+	rc = disk_printgpt(dev, prefix, verbose);
+	if (rc == 0)
+		return;
+#endif
+	disk_printmbr(dev, prefix, verbose);
+}
diff --git a/sys/boot/common/disk.h b/sys/boot/common/disk.h
new file mode 100644
index 0000000..0fc7e91
--- /dev/null
+++ b/sys/boot/common/disk.h
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Device descriptor for partitioned disks. We assume that all disk addresses
+ * are 512 byte block offsets from the start of the disk. To use, set the
+ * d_slice and d_partition variables as follows:
+ *
+ * Whole disk access:
+ *
+ * 	d_slice = -1
+ * 	d_partition = -1
+ *
+ * Whole MBR slice:
+ *
+ * 	d_slice = MBR slice number (typically 1..4)
+ * 	d_partition = -1
+ *
+ * BSD disklabel partition within an MBR slice:
+ *
+ * 	d_slice = MBR slice number (typically 1..4)
+ * 	d_partition = disklabel partition (typically 0..7)
+ *
+ * GPT partition:
+ *
+ * 	d_slice = GPT partition number (typically 1..N)
+ * 	d_partition = 255
+ *
+ * For both MBR and GPT, to automatically find the 'best' slice or partition,
+ * set d_slice to zero. This uses the partition type to decide which partition
+ * to use according to the following list of preferences:
+ *
+ * 	FreeBSD (active)
+ * 	FreeBSD (inactive)
+ * 	Linux (active)
+ * 	Linux (inactive)
+ * 	DOS/Windows (active)
+ * 	DOS/Windows (inactive)
+ *
+ * Active MBR slices (marked as bootable) are preferred over inactive. GPT
+ * doesn't have the concept of active/inactive partitions. In both MBR and GPT,
+ * if there are multiple slices/partitions of a given type, the first one
+ * is chosen.
+ *
+ * The low-level disk device will typically call slice_open() from its open
+ * method to interpret the disk partition tables according to the rules above.
+ * This will initialize d_offset to the block offset of the start of the
+ * selected partition - this offset should be added to the offset passed to
+ * the device's strategy method.
+ */
+
+#define DISK_SECSIZE	512
+
+struct disk_devdesc
+{
+	struct devsw	*d_dev;
+	int		d_type;
+	int		d_unit;
+	void		*d_opendata;
+	int		d_slice;
+	int		d_partition;
+	int		d_offset;
+};
+
+/*
+ * Parse disk metadata and initialise dev->d_offset.
+ */
+extern int disk_open(struct disk_devdesc * dev);
+
+/*
+ * Print information about slices on a disk.  For the size calculations we
+ * assume a 512 byte sector.
+ */
+extern void disk_print(struct disk_devdesc *dev, char *prefix, int verbose);
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index ee6389f..bf095bb 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -260,7 +260,7 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
     firstaddr = lastaddr = 0;
     ehdr = ef->ehdr;
     if (ef->kernel) {
-#ifdef __i386__
+#if defined(__i386__) || defined(__amd64__)
 #if __ELF_WORD_SIZE == 64
 	off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */
 #else
diff --git a/sys/boot/common/reloc_elf.c b/sys/boot/common/reloc_elf.c
index 43b7cbf..b614091 100644
--- a/sys/boot/common/reloc_elf.c
+++ b/sys/boot/common/reloc_elf.c
@@ -78,7 +78,7 @@ __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata,
 	}
 
 	return (0);
-#elif defined(__i386__) && __ELF_WORD_SIZE == 64
+#elif (defined(__i386__) || defined(__amd64__)) && __ELF_WORD_SIZE == 64
 	Elf64_Addr *where, val;
 	Elf_Addr addend, addr;
 	Elf_Size rtype, symidx;
diff --git a/sys/boot/ficl/amd64/sysdep.c b/sys/boot/ficl/amd64/sysdep.c
new file mode 100644
index 0000000..00b0d4a
--- /dev/null
+++ b/sys/boot/ficl/amd64/sysdep.c
@@ -0,0 +1,101 @@
+/*******************************************************************
+** s y s d e p . c
+** Forth Inspired Command Language
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 16 Oct 1997
+** Implementations of FICL external interface functions... 
+**
+*******************************************************************/
+
+/* $FreeBSD$ */
+
+#ifdef TESTMAIN
+#include 
+#include 
+#else
+#include 
+#endif
+#include "ficl.h"
+
+/*
+*******************  FreeBSD  P O R T   B E G I N S   H E R E ******************** Michael Smith
+*/
+
+#if PORTABLE_LONGMULDIV == 0
+DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
+{
+    DPUNS q;
+    u_int64_t qx;
+
+    qx = (u_int64_t)x * (u_int64_t) y;
+
+    q.hi = (u_int32_t)( qx >> 32 );
+    q.lo = (u_int32_t)( qx & 0xFFFFFFFFL);
+
+    return q;
+}
+
+UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
+{
+    UNSQR result;
+    u_int64_t qx, qh;
+
+    qh = q.hi;
+    qx = (qh << 32) | q.lo;
+
+    result.quot = qx / y;
+    result.rem  = qx % y;
+
+    return result;
+}
+#endif
+
+void  ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
+{
+    IGNORE(pVM);
+
+    while(*msg != 0)
+	putchar(*(msg++));
+    if (fNewline)
+	putchar('\n');
+
+   return;
+}
+
+void *ficlMalloc (size_t size)
+{
+    return malloc(size);
+}
+
+void *ficlRealloc (void *p, size_t size)
+{
+    return realloc(p, size);
+}
+
+void  ficlFree   (void *p)
+{
+    free(p);
+}
+
+
+/*
+** Stub function for dictionary access control - does nothing
+** by default, user can redefine to guarantee exclusive dict
+** access to a single thread for updates. All dict update code
+** is guaranteed to be bracketed as follows:
+** ficlLockDictionary(TRUE);
+** 
+** ficlLockDictionary(FALSE);
+**
+** Returns zero if successful, nonzero if unable to acquire lock
+** befor timeout (optional - could also block forever)
+*/
+#if FICL_MULTITHREAD
+int ficlLockDictionary(short fLock)
+{
+	IGNORE(fLock);
+	return 0;
+}
+#endif /* FICL_MULTITHREAD */
+
+
diff --git a/sys/boot/ficl/amd64/sysdep.h b/sys/boot/ficl/amd64/sysdep.h
new file mode 100644
index 0000000..08bc0e1
--- /dev/null
+++ b/sys/boot/ficl/amd64/sysdep.h
@@ -0,0 +1,434 @@
+/*******************************************************************
+                    s y s d e p . h
+** Forth Inspired Command Language
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 16 Oct 1997
+** Ficl system dependent types and prototypes...
+**
+** Note: Ficl also depends on the use of "assert" when
+** FICL_ROBUST is enabled. This may require some consideration
+** in firmware systems since assert often
+** assumes stderr/stdout.  
+** $Id: sysdep.h,v 1.11 2001/12/05 07:21:34 jsadler Exp $
+*******************************************************************/
+/*
+** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+** All rights reserved.
+**
+** Get the latest Ficl release at http://ficl.sourceforge.net
+**
+** I am interested in hearing from anyone who uses ficl. If you have
+** a problem, a success story, a defect, an enhancement request, or
+** if you would like to contribute to the ficl release, please
+** contact me by email at the address above.
+**
+** L I C E N S E  and  D I S C L A I M E R
+** 
+** 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.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+**
+** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $
+*/
+
+/* $FreeBSD$ */
+
+#if !defined (__SYSDEP_H__)
+#define __SYSDEP_H__ 
+
+#include 
+
+#include  /* size_t, NULL */
+#include 
+#include 
+
+#if !defined IGNORE		/* Macro to silence unused param warnings */
+#define IGNORE(x) &x
+#endif
+
+/*
+** TRUE and FALSE for C boolean operations, and
+** portable 32 bit types for CELLs
+** 
+*/
+#if !defined TRUE
+#define TRUE 1
+#endif
+#if !defined FALSE
+#define FALSE 0
+#endif
+
+/*
+** System dependent data type declarations...
+*/
+#if !defined INT32
+#define INT32 int
+#endif
+
+#if !defined UNS32
+#define UNS32 unsigned int
+#endif
+
+#if !defined UNS16
+#define UNS16 unsigned short
+#endif
+
+#if !defined UNS8
+#define UNS8 unsigned char
+#endif
+
+#if !defined NULL
+#define NULL ((void *)0)
+#endif
+
+/*
+** FICL_UNS and FICL_INT must have the same size as a void* on
+** the target system. A CELL is a union of void*, FICL_UNS, and
+** FICL_INT. 
+** (11/2000: same for FICL_FLOAT)
+*/
+#if !defined FICL_INT
+#define FICL_INT long
+#endif
+
+#if !defined FICL_UNS
+#define FICL_UNS unsigned long
+#endif
+
+#if !defined FICL_FLOAT
+#define FICL_FLOAT float
+#endif
+
+/*
+** Ficl presently supports values of 32 and 64 for BITS_PER_CELL
+*/
+#if !defined BITS_PER_CELL
+#define BITS_PER_CELL 64
+#endif
+
+#if ((BITS_PER_CELL != 32) && (BITS_PER_CELL != 64))
+    Error!
+#endif
+
+typedef struct
+{
+    FICL_UNS hi;
+    FICL_UNS lo;
+} DPUNS;
+
+typedef struct
+{
+    FICL_UNS quot;
+    FICL_UNS rem;
+} UNSQR;
+
+typedef struct
+{
+    FICL_INT hi;
+    FICL_INT lo;
+} DPINT;
+
+typedef struct
+{
+    FICL_INT quot;
+    FICL_INT rem;
+} INTQR;
+
+
+/*
+** B U I L D   C O N T R O L S
+*/
+
+#if !defined (FICL_MINIMAL)
+#define FICL_MINIMAL 0
+#endif
+#if (FICL_MINIMAL)
+#define FICL_WANT_SOFTWORDS  0
+#define FICL_WANT_FILE       0
+#define FICL_WANT_FLOAT      0
+#define FICL_WANT_USER       0
+#define FICL_WANT_LOCALS     0
+#define FICL_WANT_DEBUGGER   0
+#define FICL_WANT_OOP        0
+#define FICL_PLATFORM_EXTEND 0
+#define FICL_MULTITHREAD     0
+#define FICL_ROBUST          0
+#define FICL_EXTENDED_PREFIX 0
+#endif
+
+/*
+** FICL_PLATFORM_EXTEND
+** Includes words defined in ficlCompilePlatform
+*/
+#if !defined (FICL_PLATFORM_EXTEND)
+#define FICL_PLATFORM_EXTEND 1
+#endif
+
+
+/*
+** FICL_WANT_FILE
+** Includes the FILE and FILE-EXT wordset and associated code. Turn this off if you do not
+** have a filesystem!
+** Contributed by Larry Hastings
+*/
+#if !defined (FICL_WANT_FILE)
+#define FICL_WANT_FILE 0
+#endif
+
+/*
+** FICL_WANT_FLOAT
+** Includes a floating point stack for the VM, and words to do float operations.
+** Contributed by Guy Carver
+*/
+#if !defined (FICL_WANT_FLOAT)
+#define FICL_WANT_FLOAT 0
+#endif
+
+/*
+** FICL_WANT_DEBUGGER
+** Inludes a simple source level debugger
+*/
+#if !defined (FICL_WANT_DEBUGGER)
+#define FICL_WANT_DEBUGGER 1
+#endif
+
+/*
+** FICL_EXTENDED_PREFIX enables a bunch of extra prefixes in prefix.c and prefix.fr (if
+** included as part of softcore.c)
+*/
+#if !defined FICL_EXTENDED_PREFIX
+#define FICL_EXTENDED_PREFIX 0
+#endif
+
+/*
+** User variables: per-instance variables bound to the VM.
+** Kinda like thread-local storage. Could be implemented in a 
+** VM private dictionary, but I've chosen the lower overhead
+** approach of an array of CELLs instead.
+*/
+#if !defined FICL_WANT_USER
+#define FICL_WANT_USER 1
+#endif
+
+#if !defined FICL_USER_CELLS
+#define FICL_USER_CELLS 16
+#endif
+
+/* 
+** FICL_WANT_LOCALS controls the creation of the LOCALS wordset and
+** a private dictionary for local variable compilation.
+*/
+#if !defined FICL_WANT_LOCALS
+#define FICL_WANT_LOCALS 1
+#endif
+
+/* Max number of local variables per definition */
+#if !defined FICL_MAX_LOCALS
+#define FICL_MAX_LOCALS 16
+#endif
+
+/*
+** FICL_WANT_OOP
+** Inludes object oriented programming support (in softwords)
+** OOP support requires locals and user variables!
+*/
+#if !(FICL_WANT_LOCALS) || !(FICL_WANT_USER)
+#if !defined (FICL_WANT_OOP)
+#define FICL_WANT_OOP 0
+#endif
+#endif
+
+#if !defined (FICL_WANT_OOP)
+#define FICL_WANT_OOP 1
+#endif
+
+/*
+** FICL_WANT_SOFTWORDS
+** Controls inclusion of all softwords in softcore.c
+*/
+#if !defined (FICL_WANT_SOFTWORDS)
+#define FICL_WANT_SOFTWORDS 1
+#endif
+
+/*
+** FICL_MULTITHREAD enables dictionary mutual exclusion
+** wia the ficlLockDictionary system dependent function.
+** Note: this implementation is experimental and poorly
+** tested. Further, it's unnecessary unless you really
+** intend to have multiple SESSIONS (poor choice of name
+** on my part) - that is, threads that modify the dictionary
+** at the same time.
+*/
+#if !defined FICL_MULTITHREAD
+#define FICL_MULTITHREAD 0
+#endif
+
+/*
+** PORTABLE_LONGMULDIV causes ficlLongMul and ficlLongDiv to be
+** defined in C in sysdep.c. Use this if you cannot easily 
+** generate an inline asm definition
+*/ 
+#if !defined (PORTABLE_LONGMULDIV)
+#define PORTABLE_LONGMULDIV 0
+#endif
+
+/*
+** INLINE_INNER_LOOP causes the inner interpreter to be inline code
+** instead of a function call. This is mainly because MS VC++ 5
+** chokes with an internal compiler error on the function version.
+** in release mode. Sheesh.
+*/
+#if !defined INLINE_INNER_LOOP
+#if defined _DEBUG
+#define INLINE_INNER_LOOP 0
+#else
+#define INLINE_INNER_LOOP 1
+#endif
+#endif
+
+/*
+** FICL_ROBUST enables bounds checking of stacks and the dictionary.
+** This will detect stack over and underflows and dictionary overflows.
+** Any exceptional condition will result in an assertion failure.
+** (As generated by the ANSI assert macro)
+** FICL_ROBUST == 1 --> stack checking in the outer interpreter
+** FICL_ROBUST == 2 also enables checking in many primitives
+*/
+
+#if !defined FICL_ROBUST
+#define FICL_ROBUST 2
+#endif
+
+/*
+** FICL_DEFAULT_STACK Specifies the default size (in CELLs) of
+** a new virtual machine's stacks, unless overridden at 
+** create time.
+*/
+#if !defined FICL_DEFAULT_STACK
+#define FICL_DEFAULT_STACK 128
+#endif
+
+/*
+** FICL_DEFAULT_DICT specifies the number of CELLs to allocate
+** for the system dictionary by default. The value
+** can be overridden at startup time as well.
+** FICL_DEFAULT_ENV specifies the number of cells to allot
+** for the environment-query dictionary.
+*/
+#if !defined FICL_DEFAULT_DICT
+#define FICL_DEFAULT_DICT 12288
+#endif
+
+#if !defined FICL_DEFAULT_ENV
+#define FICL_DEFAULT_ENV 260
+#endif
+
+/*
+** FICL_DEFAULT_VOCS specifies the maximum number of wordlists in 
+** the dictionary search order. See Forth DPANS sec 16.3.3
+** (file://dpans16.htm#16.3.3)
+*/
+#if !defined FICL_DEFAULT_VOCS
+#define FICL_DEFAULT_VOCS 16
+#endif
+
+/*
+** FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM structure
+** that stores pointers to parser extension functions. I would never expect to have
+** more than 8 of these, so that's the default limit. Too many of these functions
+** will probably exact a nasty performance penalty.
+*/
+#if !defined FICL_MAX_PARSE_STEPS
+#define FICL_MAX_PARSE_STEPS 8
+#endif
+
+/*
+** FICL_ALIGN is the power of two to which the dictionary
+** pointer address must be aligned. This value is usually
+** either 1 or 2, depending on the memory architecture
+** of the target system; 2 is safe on any 16 or 32 bit
+** machine. 3 would be appropriate for a 64 bit machine.
+*/
+#if !defined FICL_ALIGN
+#define FICL_ALIGN 3
+#define FICL_ALIGN_ADD ((1 << FICL_ALIGN) - 1)
+#endif
+
+/*
+** System dependent routines --
+** edit the implementations in sysdep.c to be compatible
+** with your runtime environment...
+** ficlTextOut sends a NULL terminated string to the 
+**   default output device - used for system error messages
+** ficlMalloc and ficlFree have the same semantics as malloc and free
+**   in standard C
+** ficlLongMul multiplies two UNS32s and returns a 64 bit unsigned 
+**   product
+** ficlLongDiv divides an UNS64 by an UNS32 and returns UNS32 quotient
+**   and remainder
+*/
+struct vm;
+void  ficlTextOut(struct vm *pVM, char *msg, int fNewline);
+void *ficlMalloc (size_t size);
+void  ficlFree   (void *p);
+void *ficlRealloc(void *p, size_t size);
+/*
+** Stub function for dictionary access control - does nothing
+** by default, user can redefine to guarantee exclusive dict
+** access to a single thread for updates. All dict update code
+** must be bracketed as follows:
+** ficlLockDictionary(TRUE);
+** 
+** ficlLockDictionary(FALSE);
+**
+** Returns zero if successful, nonzero if unable to acquire lock
+** before timeout (optional - could also block forever)
+**
+** NOTE: this function must be implemented with lock counting
+** semantics: nested calls must behave properly.
+*/
+#if FICL_MULTITHREAD
+int ficlLockDictionary(short fLock);
+#else
+#define ficlLockDictionary(x) 0 /* ignore */
+#endif
+
+/*
+** 64 bit integer math support routines: multiply two UNS32s
+** to get a 64 bit product, & divide the product by an UNS32
+** to get an UNS32 quotient and remainder. Much easier in asm
+** on a 32 bit CPU than in C, which usually doesn't support 
+** the double length result (but it should).
+*/
+DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
+UNSQR ficlLongDiv(DPUNS    q, FICL_UNS y);
+
+
+/*
+** FICL_HAVE_FTRUNCATE indicates whether the current OS supports
+** the ftruncate() function (available on most UNIXes).  This
+** function is necessary to provide the complete File-Access wordset.
+*/
+#if !defined (FICL_HAVE_FTRUNCATE)
+#define FICL_HAVE_FTRUNCATE 0
+#endif
+
+
+#endif /*__SYSDEP_H__*/
diff --git a/sys/boot/i386/libi386/bioscd.c b/sys/boot/i386/libi386/bioscd.c
index a6dba0c..a3abf34 100644
--- a/sys/boot/i386/libi386/bioscd.c
+++ b/sys/boot/i386/libi386/bioscd.c
@@ -117,6 +117,7 @@ bc_bios2unit(int biosdev)
 	int i;
     
 	DEBUG("looking for bios device 0x%x", biosdev);
+	printf("looking for bios device 0x%x, nbcinfo=%d\n", biosdev, nbcinfo);
 	for (i = 0; i < nbcinfo; i++) {
 		DEBUG("bc unit %d is BIOS device 0x%x", i, bcinfo[i].bc_unit);
 		if (bcinfo[i].bc_unit == biosdev)
@@ -148,6 +149,7 @@ bc_init(void)
 int
 bc_add(int biosdev)
 {
+	printf("bc_add(%d)\n", biosdev);
 
 	if (nbcinfo >= MAXBCDEV)
 		return (-1);
@@ -159,8 +161,10 @@ bc_add(int biosdev)
 	v86.ds = VTOPSEG(&bcinfo[nbcinfo].bc_sp);
 	v86.esi = VTOPOFF(&bcinfo[nbcinfo].bc_sp);
 	v86int();
-	if ((v86.eax & 0xff00) != 0)
+	if ((v86.eax & 0xff00) != 0) {
+                printf("CD probe failed, eax=0x%08x\n", v86.eax);
 		return (-1);
+        }
 
 	printf("BIOS CD is cd%d\n", nbcinfo);
 	nbcinfo++;
diff --git a/sys/boot/userboot/Makefile b/sys/boot/userboot/Makefile
new file mode 100644
index 0000000..f15c905
--- /dev/null
+++ b/sys/boot/userboot/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.include 
+
+SUBDIR=		ficl libstand test userboot
+
+.include 
+
diff --git a/sys/boot/userboot/ficl/Makefile b/sys/boot/userboot/ficl/Makefile
new file mode 100644
index 0000000..af5d1461
--- /dev/null
+++ b/sys/boot/userboot/ficl/Makefile
@@ -0,0 +1,73 @@
+# $FreeBSD$
+#
+.include 
+MK_SSP=		no
+
+.PATH: ${.CURDIR}/../../ficl
+.PATH: ${.CURDIR}/../../ficl/${MACHINE_CPUARCH}
+BASE_SRCS=	dict.c ficl.c fileaccess.c float.c loader.c math64.c \
+		prefix.c search.c stack.c tools.c vm.c words.c
+
+SRCS=		${BASE_SRCS} sysdep.c softcore.c
+CLEANFILES=	softcore.c testmain testmain.o
+CFLAGS+=	-ffreestanding -fPIC
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+=	-mno-mmx -mno-3dnow -mno-sse -mno-sse2
+.endif
+.if ${MACHINE_CPUARCH} == "i386"
+CFLAGS+=	-mpreferred-stack-boundary=2
+CFLAGS+=	-mno-sse3
+.endif
+.if ${MACHINE_CPUARCH} == "powerpc" || ${MACHINE_CPUARCH} == "arm"
+CFLAGS+=	-msoft-float
+.endif
+.if ${MACHINE} == "pc98"
+CFLAGS+=	-Os -DPC98
+.endif
+.if HAVE_PNP
+CFLAGS+=	-DHAVE_PNP
+.endif
+.ifmake testmain
+CFLAGS+=	-DTESTMAIN -D_TESTMAIN
+SRCS+=		testmain.c
+PROG=		testmain
+.include 
+.else
+LIB=		ficl
+INTERNALLIB=
+.include 
+.endif
+
+# Standard softwords
+.PATH: ${.CURDIR}/../../ficl/softwords
+SOFTWORDS=	softcore.fr jhlocal.fr marker.fr freebsd.fr ficllocal.fr \
+		ifbrack.fr
+# Optional OO extension softwords
+#SOFTWORDS+=	oo.fr classes.fr
+
+#.if ${MACHINE_CPUARCH} == "amd64"
+#CFLAGS+=	-m32 -march=i386 -I.
+#.endif
+
+.if ${MACHINE_ARCH} == "powerpc64"
+CFLAGS+=	-m32 -mcpu=powerpc -I.
+.endif
+
+CFLAGS+=	-I${.CURDIR}/../../ficl
+CFLAGS+=	-I${.CURDIR}/../../ficl/${MACHINE_CPUARCH}
+CFLAGS+=	-I${.CURDIR}/../../common
+
+softcore.c: ${SOFTWORDS} softcore.awk
+	(cd ${.CURDIR}/../../ficl/softwords; cat ${SOFTWORDS} \
+	    | awk -f softcore.awk -v datestamp="`LC_ALL=C date`") > ${.TARGET}
+
+#.if ${MACHINE_CPUARCH} == "amd64"
+#${SRCS:M*.c:R:S/$/.o/g}: machine
+#
+#beforedepend ${OBJS}: machine
+#
+#machine:
+#	ln -sf ${.CURDIR}/../../i386/include machine
+#
+#CLEANFILES+=	machine
+#.endif
diff --git a/sys/boot/userboot/libstand/Makefile b/sys/boot/userboot/libstand/Makefile
new file mode 100644
index 0000000..9e71a24
--- /dev/null
+++ b/sys/boot/userboot/libstand/Makefile
@@ -0,0 +1,161 @@
+# $FreeBSD$
+# Originally from	$NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $
+#
+# Notes:
+# - We don't use the libc strerror/sys_errlist because the string table is
+#   quite large.
+#
+
+WITHOUT_SSP=
+NO_MAN=
+
+.include 
+
+S=		${.CURDIR}/../../../../lib/libstand
+
+.PATH:		${S}
+LIB=		stand
+INTERNALLIB=
+NO_PROFILE=
+NO_PIC=
+
+WARNS?=		0
+
+CFLAGS+= -ffreestanding -Wformat -fPIC
+CFLAGS+= -I${.CURDIR}/../../../../lib/libstand
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+=	-mno-mmx -mno-3dnow -mno-sse -mno-sse2
+.endif
+.if ${MACHINE_CPUARCH} == "i386"
+CFLAGS+=	-mpreferred-stack-boundary=2
+CFLAGS+=	-mno-sse3
+.endif
+.if ${MACHINE} == "pc98"
+CFLAGS+=	-Os
+.endif
+.if ${MACHINE_CPUARCH} == "powerpc"
+CFLAGS+=	-msoft-float -D_STANDALONE -DNETIF_DEBUG
+.endif
+.if ${MACHINE_CPUARCH} == "arm"
+CFLAGS+=	-msoft-float -D_STANDALONE
+.endif
+
+# standalone components and stuff we have modified locally
+SRCS+=	zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \
+	globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \
+	sbrk.c twiddle.c zalloc.c zalloc_malloc.c
+
+# private (pruned) versions of libc string functions
+SRCS+=	strcasecmp.c
+
+LIBC=	${.CURDIR}/../../../../lib/libc
+
+.PATH: ${LIBC}/net
+
+SRCS+= ntoh.c
+
+# string functions from libc
+.PATH: ${LIBC}/string
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "powerpc" || \
+	${MACHINE_CPUARCH} == "sparc64" || ${MACHINE_CPUARCH} == "amd64" || \
+	${MACHINE_CPUARCH} == "arm"
+SRCS+=	bcmp.c bcopy.c bzero.c ffs.c index.c memccpy.c memchr.c memcmp.c \
+        memcpy.c memmove.c memset.c qdivrem.c rindex.c strcat.c strchr.c \
+        strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c \
+	strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
+.endif
+.if ${MACHINE_CPUARCH} == "arm"
+.PATH: ${LIBC}/arm/gen
+SRCS+= divsi3.S
+.endif
+.if ${MACHINE_CPUARCH} == "ia64"
+.PATH: ${LIBC}/ia64/string
+SRCS+=	bcmp.c bcopy.S bzero.S ffs.S index.c memccpy.c memchr.c memcmp.c \
+	memcpy.S memmove.S memset.c rindex.c strcat.c strchr.c \
+	strcmp.c strcpy.c strcspn.c strlen.c \
+	strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strsep.c \
+	strspn.c strstr.c strtok.c swab.c
+
+.PATH: ${LIBC}/ia64/gen
+SRCS+= __divdi3.S __divsi3.S __moddi3.S __modsi3.S
+SRCS+= __udivdi3.S __udivsi3.S __umoddi3.S __umodsi3.S
+.endif
+.if ${MACHINE_CPUARCH} == "powerpc"
+.PATH: ${LIBC}/libc/quad
+SRCS+=	ashldi3.c ashrdi3.c
+.PATH: ${LIBC}/powerpc/gen
+SRCS+=	syncicache.c
+.endif
+
+# uuid functions from libc
+.PATH: ${LIBC}/uuid
+SRCS+= uuid_equal.c uuid_is_nil.c
+
+# _setjmp/_longjmp
+.if ${MACHINE_CPUARCH} == "amd64"
+.PATH: ${.CURDIR}/amd64
+.elif ${MACHINE_ARCH} == "powerpc64"
+.PATH: ${S}/powerpc
+.else
+.PATH: ${S}/${MACHINE_CPUARCH}
+.endif
+SRCS+=	_setjmp.S
+
+# decompression functionality from libbz2
+# NOTE: to actually test this functionality after libbz2 upgrade compile
+# loader(8) with LOADER_BZIP2_SUPPORT defined
+.PATH: ${.CURDIR}/../../../../contrib/bzip2
+CFLAGS+= -DBZ_NO_STDIO -DBZ_NO_COMPRESS
+SRCS+=	libstand_bzlib_private.h
+
+.for file in bzlib.c crctable.c decompress.c huffman.c randtable.c
+SRCS+=	_${file}
+CLEANFILES+=	_${file}
+
+_${file}: ${file}
+	sed "s|bzlib_private\.h|libstand_bzlib_private.h|" ${.ALLSRC} > ${.TARGET}
+.endfor
+
+CLEANFILES+= libstand_bzlib_private.h
+libstand_bzlib_private.h: bzlib_private.h
+	sed -e 's||"stand.h"|' \
+		${.ALLSRC} > ${.TARGET}
+
+# decompression functionality from libz
+.PATH: ${.CURDIR}/../../../../lib/libz
+CFLAGS+=-DHAVE_MEMCPY -I${.CURDIR}/../../../../lib/libz
+SRCS+=	adler32.c crc32.c libstand_zutil.h
+
+.for file in infback.c inffast.c inflate.c inftrees.c zutil.c
+SRCS+=	_${file}
+CLEANFILES+=	_${file}
+
+_${file}: ${file}
+	sed "s|zutil\.h|libstand_zutil.h|" ${.ALLSRC} > ${.TARGET}
+.endfor
+
+# depend on stand.h being able to be included multiple times
+CLEANFILES+= libstand_zutil.h
+libstand_zutil.h: zutil.h
+	sed -e 's||"stand.h"|' \
+	    -e 's||"stand.h"|' \
+	    -e 's||"stand.h"|' \
+	    ${.ALLSRC} > ${.TARGET}
+
+# io routines
+SRCS+=	closeall.c dev.c ioctl.c nullfs.c stat.c \
+	fstat.c close.c lseek.c open.c read.c write.c readdir.c
+
+# network routines
+SRCS+=	arp.c ether.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c
+
+# network info services:
+SRCS+=	bootp.c rarp.c bootparam.c
+
+# boot filesystems
+SRCS+=	ufs.c nfs.c cd9660.c tftp.c gzipfs.c bzipfs.c
+SRCS+=	dosfs.c ext2fs.c
+SRCS+=	splitfs.c
+
+.include 
diff --git a/sys/boot/userboot/libstand/amd64/_setjmp.S b/sys/boot/userboot/libstand/amd64/_setjmp.S
new file mode 100644
index 0000000..e841f49
--- /dev/null
+++ b/sys/boot/userboot/libstand/amd64/_setjmp.S
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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.
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+	.asciz "@(#)_setjmp.s	5.1 (Berkeley) 4/23/90"
+#endif /* LIBC_SCCS and not lint */
+#include 
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ *	_longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ *	_setjmp(a)
+ * by restoring registers from the environment 'a'.
+ * The previous signal state is NOT restored.
+ */
+
+ENTRY(_setjmp)
+	movq	%rdi,%rax
+	movq	0(%rsp),%rdx		/* retval */
+	movq	%rdx, 0(%rax)		/* 0; retval */
+	movq	%rbx, 8(%rax)		/* 1; rbx */
+	movq	%rsp,16(%rax)		/* 2; rsp */
+	movq	%rbp,24(%rax)		/* 3; rbp */
+	movq	%r12,32(%rax)		/* 4; r12 */
+	movq	%r13,40(%rax)		/* 5; r13 */
+	movq	%r14,48(%rax)		/* 6; r14 */
+	movq	%r15,56(%rax)		/* 7; r15 */
+	fnstcw	64(%rax)		/* 8; fpu cw */
+	stmxcsr	68(%rax)		/*    and mxcsr */
+	xorq	%rax,%rax
+	ret
+END(_setjmp)
+
+	.weak	CNAME(_longjmp)
+ENTRY(_longjmp)
+	movq	%rdi,%rdx
+	/* Restore the mxcsr, but leave exception flags intact. */
+	stmxcsr	-4(%rsp)
+	movl	68(%rdx),%eax
+	andl	$0xffffffc0,%eax
+	movl	-4(%rsp),%edi
+	andl	$0x3f,%edi
+	xorl	%eax,%edi
+	movl	%edi,-4(%rsp)
+	ldmxcsr -4(%rsp)
+	movq	%rsi,%rax		/* retval */
+	movq	0(%rdx),%rcx
+	movq	8(%rdx),%rbx
+	movq	16(%rdx),%rsp
+	movq	24(%rdx),%rbp
+	movq	32(%rdx),%r12
+	movq	40(%rdx),%r13
+	movq	48(%rdx),%r14
+	movq	56(%rdx),%r15
+	fldcw	64(%rdx)
+	testq	%rax,%rax
+	jnz	1f
+	incq	%rax
+1:	movq	%rcx,0(%rsp)
+	ret
+END(_longjmp)
diff --git a/sys/boot/userboot/test/Makefile b/sys/boot/userboot/test/Makefile
new file mode 100644
index 0000000..24d89b7
--- /dev/null
+++ b/sys/boot/userboot/test/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+
+NO_MAN=
+WITHOUT_SSP=
+
+.include 
+
+PROG=		test
+INTERNALPROG=
+
+CFLAGS+=	-I${.CURDIR}/..
+CFLAGS+=	-I${.CURDIR}/../../..
+
+.include 
diff --git a/sys/boot/userboot/test/test.c b/sys/boot/userboot/test/test.c
new file mode 100644
index 0000000..a752a80
--- /dev/null
+++ b/sys/boot/userboot/test/test.c
@@ -0,0 +1,428 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+char *host_base = NULL;
+struct termios term, oldterm;
+char *image;
+size_t image_size;
+int disk_fd = -1;
+
+uint64_t regs[16];
+uint64_t pc;
+
+void test_exit(void *arg, int v);
+
+/*
+ * Console i/o
+ */
+
+void
+test_putc(void *arg, int ch)
+{
+	char c = ch;
+
+	write(1, &c, 1);
+}
+
+int
+test_getc(void *arg)
+{
+	char c;
+
+	if (read(0, &c, 1) == 1)
+		return c;
+	return -1;
+}
+
+int
+test_poll(void *arg)
+{
+	int n;
+
+	if (ioctl(0, FIONREAD, &n) >= 0)
+		return (n > 0);
+	return (0);
+}
+
+/*
+ * Host filesystem i/o
+ */
+
+struct test_file {
+	int tf_isdir;
+	size_t tf_size;
+	struct stat tf_stat;
+	union {
+		int fd;
+		DIR *dir;
+	} tf_u;
+};
+
+int
+test_open(void *arg, const char *filename, void **h_return)
+{
+	struct stat st;
+	struct test_file *tf;
+	char path[PATH_MAX];
+
+	if (!host_base)
+		return (ENOENT);
+
+	strlcpy(path, host_base, PATH_MAX);
+	if (path[strlen(path) - 1] == '/')
+		path[strlen(path) - 1] = 0;
+	strlcat(path, filename, PATH_MAX);
+	tf = malloc(sizeof(struct test_file));
+	if (stat(path, &tf->tf_stat) < 0) {
+		free(tf);
+		return (errno);
+	}
+
+	tf->tf_size = st.st_size;
+	if (S_ISDIR(tf->tf_stat.st_mode)) {
+		tf->tf_isdir = 1;
+		tf->tf_u.dir = opendir(path);
+		if (!tf->tf_u.dir)
+			goto out;
+                *h_return = tf;
+		return (0);
+	}
+	if (S_ISREG(tf->tf_stat.st_mode)) {
+		tf->tf_isdir = 0;
+		tf->tf_u.fd = open(path, O_RDONLY);
+		if (tf->tf_u.fd < 0)
+			goto out;
+                *h_return = tf;
+		return (0);
+	}
+
+out:
+	free(tf);
+	return (EINVAL);
+}
+
+int
+test_close(void *arg, void *h)
+{
+	struct test_file *tf = h;
+
+	if (tf->tf_isdir)
+		closedir(tf->tf_u.dir);
+	else
+		close(tf->tf_u.fd);
+	free(tf);
+
+	return (0);
+}
+
+int
+test_isdir(void *arg, void *h)
+{
+	struct test_file *tf = h;
+
+	return (tf->tf_isdir);
+}
+
+int
+test_read(void *arg, void *h, void *dst, size_t size, size_t *resid_return)
+{
+	struct test_file *tf = h;
+	ssize_t sz;
+
+	if (tf->tf_isdir)
+		return (EINVAL);
+	sz = read(tf->tf_u.fd, dst, size);
+	if (sz < 0)
+		return (EINVAL);
+	*resid_return = size - sz;
+	return (0);
+}
+
+int
+test_readdir(void *arg, void *h, uint32_t *fileno_return, uint8_t *type_return,
+    size_t *namelen_return, char *name)
+{
+	struct test_file *tf = h;
+	struct dirent *dp;
+
+	if (!tf->tf_isdir)
+		return (EINVAL);
+
+	dp = readdir(tf->tf_u.dir);
+	if (!dp)
+		return (ENOENT);
+
+	/*
+	 * Note: d_namlen is in the range 0..255 and therefore less
+	 * than PATH_MAX so we don't need to test before copying.
+	 */
+	*fileno_return = dp->d_fileno;
+	*type_return = dp->d_type;
+	*namelen_return = dp->d_namlen;
+	memcpy(name, dp->d_name, dp->d_namlen);
+	name[dp->d_namlen] = 0;
+
+	return (0);
+}
+
+int
+test_seek(void *arg, void *h, uint64_t offset, int whence)
+{
+	struct test_file *tf = h;
+
+	if (tf->tf_isdir)
+		return (EINVAL);
+	if (lseek(tf->tf_u.fd, offset, whence) < 0)
+		return (errno);
+	return (0);
+}
+
+int
+test_stat(void *arg, void *h, int *mode_return, int *uid_return, int *gid_return,
+    uint64_t *size_return)
+{
+	struct test_file *tf = h;
+
+	*mode_return = tf->tf_stat.st_mode;
+	*uid_return = tf->tf_stat.st_uid;
+	*gid_return = tf->tf_stat.st_gid;
+	*size_return = tf->tf_stat.st_size;
+	return (0);
+}
+
+/*
+ * Disk image i/o
+ */
+
+int
+test_diskread(void *arg, int unit, uint64_t offset, void *dst, size_t size,
+    size_t *resid_return)
+{
+	ssize_t n;
+
+	if (unit != 0 || disk_fd == -1)
+		return (EIO);
+	n = pread(disk_fd, dst, size, offset);
+	if (n < 0)
+		return (errno);
+	*resid_return = size - n;
+	return (0);
+}
+
+/*
+ * Guest virtual machine i/o
+ *
+ * Note: guest addresses are kernel virtual
+ */
+
+int
+test_copyin(void *arg, const void *from, uint64_t to, size_t size)
+{
+
+	to &= 0x7fffffff;
+	if (to > image_size)
+		return (EFAULT);
+	if (to + size > image_size)
+		size = image_size - to;
+	memcpy(&image[to], from, size);
+}
+
+int
+test_copyout(void *arg, uint64_t from, void *to, size_t size)
+{
+
+	from &= 0x7fffffff;
+	if (from > image_size)
+		return (EFAULT);
+	if (from + size > image_size)
+		size = image_size - from;
+	memcpy(to, &image[from], size);
+}
+
+void
+test_setreg(void *arg, int r, uint64_t v)
+{
+
+	if (r < 0 || r >= 16)
+		return;
+	regs[r] = v;
+}
+
+void
+test_setmsr(void *arg, int r, uint64_t v)
+{
+}
+
+void
+test_setcr(void *arg, int r, uint64_t v)
+{
+}
+
+void
+test_setgdt(void *arg, uint64_t v, size_t sz)
+{
+}
+
+void
+test_exec(void *arg, uint64_t pc)
+{
+	printf("Execute at 0x%llx\n", pc);
+	test_exit(arg, 0);
+}
+
+/*
+ * Misc
+ */
+
+void
+test_delay(void *arg, int usec)
+{
+
+	usleep(usec);
+}
+
+void
+test_exit(void *arg, int v)
+{
+
+	tcsetattr(0, TCSAFLUSH, &oldterm);
+	exit(v);
+}
+
+void
+test_getmem(void *arg, uint64_t *lowmem, uint64_t *highmem)
+{
+
+        *lowmem = 128*1024*1024;
+        *highmem = 0;
+}
+
+struct loader_callbacks_v1 cb = {
+	.putc = test_putc,
+	.getc = test_getc,
+	.poll = test_poll,
+
+	.open = test_open,
+	.close = test_close,
+	.isdir = test_isdir,
+	.read = test_read,
+	.readdir = test_readdir,
+	.seek = test_seek,
+	.stat = test_stat,
+
+	.diskread = test_diskread,
+
+	.copyin = test_copyin,
+	.copyout = test_copyout,
+	.setreg = test_setreg,
+	.setmsr = test_setmsr,
+	.setcr = test_setcr,
+        .setgdt = test_setgdt,
+	.exec = test_exec,
+
+	.delay = test_delay,
+	.exit = test_exit,
+        .getmem = test_getmem,
+};
+
+void
+usage()
+{
+
+	printf("usage: %s [-d ] [-h \n");
+	exit(1);
+}
+
+int
+main(int argc, char** argv)
+{
+	void *h;
+	void (*func)(struct loader_callbacks_v1 *, void *, int, int);
+	int opt;
+	char *disk_image = NULL;
+
+	while ((opt = getopt(argc, argv, "d:h:")) != -1) {
+		switch (opt) {
+		case 'd':
+			disk_image = optarg;
+			break;
+
+		case 'h':
+			host_base = optarg;
+			break;
+
+		case '?':
+			usage();
+		}
+	}
+
+	h = dlopen("/boot/userboot.so",
+            RTLD_LOCAL);
+	if (!h) {
+		printf("%s\n", dlerror());
+		return (1);
+	}
+	func = dlsym(h, "loader_main");
+	if (!func) {
+		printf("%s\n", dlerror());
+		return (1);
+	}
+
+	image_size = 128*1024*1024;
+	image = malloc(image_size);
+	if (disk_image) {
+		disk_fd = open(disk_image, O_RDONLY);
+		if (disk_fd < 0)
+			err(1, "Can't open disk image '%s'", disk_image);
+	}
+
+	tcgetattr(0, &term);
+	oldterm = term;
+	term.c_iflag &= ~(ICRNL);
+	term.c_lflag &= ~(ICANON|ECHO);
+	tcsetattr(0, TCSAFLUSH, &term);
+
+	func(&cb, NULL, USERBOOT_VERSION_1, disk_fd >= 0);
+}
diff --git a/sys/boot/userboot/userboot.h b/sys/boot/userboot/userboot.h
new file mode 100644
index 0000000..7d8263e
--- /dev/null
+++ b/sys/boot/userboot/userboot.h
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 2011 Doug Rabson
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * USERBOOT interface versions
+ */
+#define	USERBOOT_VERSION_1      1
+
+/*
+ * Exit codes from the loader
+ */
+#define	USERBOOT_EXIT_QUIT      1
+#define	USERBOOT_EXIT_REBOOT    2
+
+struct loader_callbacks_v1 {
+	/*
+	 * Console i/o
+	 */
+
+        /*
+         * Wait until a key is pressed on the console and then return it
+         */
+	int		(*getc)(void *arg);
+
+        /*
+         * Write the character ch to the console
+         */
+	void		(*putc)(void *arg, int ch);
+
+        /*
+         * Return non-zero if a key can be read from the console
+         */
+	int		(*poll)(void *arg);
+
+	/*
+	 * Host filesystem i/o
+	 */
+
+        /*
+         * Open a file in the host filesystem
+         */
+	int		(*open)(void *arg, const char *filename, void **h_return);
+
+        /*
+         * Close a file
+         */
+	int		(*close)(void *arg, void *h);
+
+        /*
+         * Return non-zero if the file is a directory
+         */
+	int		(*isdir)(void *arg, void *h);
+
+        /*
+         * Read size bytes from a file. The number of bytes remaining
+         * in dst after reading is returned in *resid_return
+         */
+	int		(*read)(void *arg, void *h, void *dst, size_t size,
+            size_t *resid_return);
+
+        /*
+         * Read an entry from a directory. The entry's inode number is
+         * returned in *fileno_return, its type in *type_return and
+         * the name length in *namelen_return. The name itself is
+         * copied to the buffer name which must be at least PATH_MAX
+         * in size.
+         */
+	int		(*readdir)(void *arg, void *h, uint32_t *fileno_return,
+            uint8_t *type_return, size_t *namelen_return, char *name);
+
+        /*
+         * Seek to a location within an open file
+         */
+	int		(*seek)(void *arg, void *h, uint64_t offset,
+            int whence);
+
+        /*
+         * Return some stat(2) related information about the file
+         */
+	int		(*stat)(void *arg, void *h, int *mode_return,
+            int *uid_return, int *gid_return, uint64_t *size_return);
+
+	/*
+	 * Disk image i/o
+	 */
+
+        /*
+         * Read from a disk image at the given offset
+         */
+	int		(*diskread)(void *arg, int unit, uint64_t offset,
+            void *dst, size_t size, size_t *resid_return);
+
+	/*
+	 * Guest virtual machine i/o
+	 */
+
+        /*
+         * Copy to the guest address space
+         */
+	int		(*copyin)(void *arg, const void *from,
+            uint64_t to, size_t size);
+
+        /*
+         * Copy from the guest address space
+         */
+	int		(*copyout)(void *arg, uint64_t from,
+            void *to, size_t size);
+
+        /*
+         * Set a guest register value
+         */
+	void		(*setreg)(void *arg, int, uint64_t);
+
+        /*
+         * Set a guest MSR value
+         */
+	void		(*setmsr)(void *arg, int, uint64_t);
+
+        /*
+         * Set a guest CR value
+         */
+	void		(*setcr)(void *arg, int, uint64_t);
+
+        /*
+         * Set the guest GDT address
+         */
+        void            (*setgdt)(void *arg, uint64_t, size_t);
+
+        /*
+         * Transfer control to the guest at the given address
+         */
+	void		(*exec)(void *arg, uint64_t pc);
+
+	/*
+	 * Misc
+	 */
+
+        /*
+         * Sleep for usec microseconds
+         */
+	void		(*delay)(void *arg, int usec);
+
+        /*
+         * Exit with the given exit code
+         */
+	void		(*exit)(void *arg, int v);
+
+        /*
+         * Return guest physical memory map details
+         */
+	void		(*getmem)(void *arg, uint64_t *lowmem,
+            uint64_t *highmem);
+};
diff --git a/sys/boot/userboot/userboot/Makefile b/sys/boot/userboot/userboot/Makefile
new file mode 100644
index 0000000..7271fa7
--- /dev/null
+++ b/sys/boot/userboot/userboot/Makefile
@@ -0,0 +1,61 @@
+# $FreeBSD$
+
+NO_MAN=
+WITHOUT_SSP=
+
+.include 
+
+SHLIB_NAME=	userboot.so
+NO_CTF=		yes
+STRIP=
+LIBDIR=		/boot
+
+SRCS=		autoload.c
+SRCS+=		bootinfo.c
+SRCS+=		bootinfo32.c
+SRCS+=		bootinfo64.c
+SRCS+=		conf.c
+SRCS+=		console.c
+SRCS+=		copy.c
+SRCS+=		devicename.c
+SRCS+=		elf32_freebsd.c
+SRCS+=		elf64_freebsd.c
+SRCS+=		host.c
+SRCS+=		main.c
+SRCS+=		userboot_cons.c
+SRCS+=		userboot_disk.c
+SRCS+=		vers.c
+
+CFLAGS+=	-Wall
+CFLAGS+=	-I${.CURDIR}/..
+CFLAGS+=	-I${.CURDIR}/../../common
+CFLAGS+=	-I${.CURDIR}/../../..
+CFLAGS+=	-I${.CURDIR}/../../../../lib/libstand
+CFLAGS+=	-ffreestanding -I.
+CFLAGS+=	-DLOADER_GPT_SUPPORT
+
+LDFLAGS+=	-nostdlib -Wl,-Bsymbolic
+
+NEWVERSWHAT=	"User boot" ${MACHINE_CPUARCH}
+
+vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
+	sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
+
+CLEANFILES=	vers.c
+
+.if ${MK_FORTH} != "no"
+BOOT_FORTH=	yes
+CFLAGS+=        -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/i386
+LIBFICL=	${.OBJDIR}/../ficl/libficl.a
+LIBSTAND=	${.OBJDIR}/../libstand/libstand.a
+.endif
+
+# Always add MI sources 
+.PATH:		${.CURDIR}/../../common
+.include	"${.CURDIR}/../../common/Makefile.inc"
+CFLAGS+=	-I${.CURDIR}/../../common
+CFLAGS+=	-I.
+DPADD=		${LIBFICL} ${LIBSTAND}
+LDADD=		${LIBFICL} ${LIBSTAND}
+
+.include 
diff --git a/sys/boot/userboot/userboot/autoload.c b/sys/boot/userboot/userboot/autoload.c
new file mode 100644
index 0000000..a86afcf
--- /dev/null
+++ b/sys/boot/userboot/userboot/autoload.c
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+int
+userboot_autoload(void)
+{
+
+	return (0);
+}
diff --git a/sys/boot/userboot/userboot/bootinfo.c b/sys/boot/userboot/userboot/bootinfo.c
new file mode 100644
index 0000000..75ad5e7
--- /dev/null
+++ b/sys/boot/userboot/userboot/bootinfo.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+
+#include "bootstrap.h"
+#include "libuserboot.h"
+
+/*
+ * Return a 'boothowto' value corresponding to the kernel arguments in
+ * (kargs) and any relevant environment variables.
+ */
+static struct 
+{
+    const char	*ev;
+    int		mask;
+} howto_names[] = {
+    {"boot_askname",	RB_ASKNAME},
+    {"boot_cdrom",	RB_CDROM},
+    {"boot_ddb",	RB_KDB},
+    {"boot_dfltroot",	RB_DFLTROOT},
+    {"boot_gdb",	RB_GDB},
+    {"boot_multicons",	RB_MULTIPLE},
+    {"boot_mute",	RB_MUTE},
+    {"boot_pause",	RB_PAUSE},
+    {"boot_serial",	RB_SERIAL},
+    {"boot_single",	RB_SINGLE},
+    {"boot_verbose",	RB_VERBOSE},
+    {NULL,	0}
+};
+
+int
+bi_getboothowto(char *kargs)
+{
+    char	*cp;
+    char	*curpos, *next, *string;
+    int		howto;
+    int		active;
+    int		i;
+    int		vidconsole;
+
+    /* Parse kargs */
+    howto = 0;
+    if (kargs  != NULL) {
+	cp = kargs;
+	active = 0;
+	while (*cp != 0) {
+	    if (!active && (*cp == '-')) {
+		active = 1;
+	    } else if (active)
+		switch (*cp) {
+		case 'a':
+		    howto |= RB_ASKNAME;
+		    break;
+		case 'C':
+		    howto |= RB_CDROM;
+		    break;
+		case 'd':
+		    howto |= RB_KDB;
+		    break;
+		case 'D':
+		    howto |= RB_MULTIPLE;
+		    break;
+		case 'm':
+		    howto |= RB_MUTE;
+		    break;
+		case 'g':
+		    howto |= RB_GDB;
+		    break;
+		case 'h':
+		    howto |= RB_SERIAL;
+		    break;
+		case 'p':
+		    howto |= RB_PAUSE;
+		    break;
+		case 'r':
+		    howto |= RB_DFLTROOT;
+		    break;
+		case 's':
+		    howto |= RB_SINGLE;
+		    break;
+		case 'v':
+		    howto |= RB_VERBOSE;
+		    break;
+		default:
+		    active = 0;
+		    break;
+		}
+	    cp++;
+	}
+    }
+    /* get equivalents from the environment */
+    for (i = 0; howto_names[i].ev != NULL; i++)
+	if (getenv(howto_names[i].ev) != NULL)
+	    howto |= howto_names[i].mask;
+
+    /* Enable selected consoles */
+    string = next = strdup(getenv("console"));
+    vidconsole = 0;
+    while (next != NULL) {
+	curpos = strsep(&next, " ,");
+	if (*curpos == '\0')
+		continue;
+	if (!strcmp(curpos, "vidconsole"))
+	    vidconsole = 1;
+	else if (!strcmp(curpos, "comconsole"))
+	    howto |= RB_SERIAL;
+	else if (!strcmp(curpos, "nullconsole"))
+	    howto |= RB_MUTE;
+    }
+
+    if (vidconsole && (howto & RB_SERIAL))
+	howto |= RB_MULTIPLE;
+
+    /*
+     * XXX: Note that until the kernel is ready to respect multiple consoles
+     * for the boot messages, the first named console is the primary console
+     */
+    if (!strcmp(string, "vidconsole"))
+	howto &= ~RB_SERIAL;
+
+    free(string);
+
+    return(howto);
+}
+
+void
+bi_setboothowto(int howto)
+{
+    int		i;
+
+    for (i = 0; howto_names[i].ev != NULL; i++)
+	if (howto & howto_names[i].mask)
+	    setenv(howto_names[i].ev, "YES", 1);
+}
+
+/*
+ * Copy the environment into the load area starting at (addr).
+ * Each variable is formatted as =, with a single nul
+ * separating each variable, and a double nul terminating the environment.
+ */
+vm_offset_t
+bi_copyenv(vm_offset_t addr)
+{
+    struct env_var	*ep;
+    
+    /* traverse the environment */
+    for (ep = environ; ep != NULL; ep = ep->ev_next) {
+        CALLBACK(copyin, ep->ev_name, addr, strlen(ep->ev_name));
+	addr += strlen(ep->ev_name);
+	CALLBACK(copyin, "=", addr, 1);
+	addr++;
+	if (ep->ev_value != NULL) {
+            CALLBACK(copyin, ep->ev_value, addr, strlen(ep->ev_value));
+	    addr += strlen(ep->ev_value);
+	}
+	CALLBACK(copyin, "", addr, 1);
+	addr++;
+    }
+    CALLBACK(copyin, "", addr, 1);
+    addr++;
+    return(addr);
+}
diff --git a/sys/boot/userboot/userboot/bootinfo32.c b/sys/boot/userboot/userboot/bootinfo32.c
new file mode 100644
index 0000000..00784c9
--- /dev/null
+++ b/sys/boot/userboot/userboot/bootinfo32.c
@@ -0,0 +1,264 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bootstrap.h"
+#include "libuserboot.h"
+
+static struct bootinfo  bi;
+
+/*
+ * Copy module-related data into the load area, where it can be
+ * used as a directory for loaded modules.
+ *
+ * Module data is presented in a self-describing format.  Each datum
+ * is preceded by a 32-bit identifier and a 32-bit size field.
+ *
+ * Currently, the following data are saved:
+ *
+ * MOD_NAME	(variable)		module name (string)
+ * MOD_TYPE	(variable)		module type (string)
+ * MOD_ARGS	(variable)		module parameters (string)
+ * MOD_ADDR	sizeof(vm_offset_t)	module load address
+ * MOD_SIZE	sizeof(size_t)		module size
+ * MOD_METADATA	(variable)		type-specific metadata
+ */
+#define COPY32(v, a, c) {			\
+    u_int32_t	x = (v);			\
+    if (c)					\
+        CALLBACK(copyin, &x, a, sizeof(x));	\
+    a += sizeof(x);				\
+}
+
+#define MOD_STR(t, a, s, c) {			\
+    COPY32(t, a, c);				\
+    COPY32(strlen(s) + 1, a, c);		\
+    if (c)					\
+        CALLBACK(copyin, s, a, strlen(s) + 1);  \
+    a += roundup(strlen(s) + 1, sizeof(u_long));\
+}
+
+#define MOD_NAME(a, s, c)	MOD_STR(MODINFO_NAME, a, s, c)
+#define MOD_TYPE(a, s, c)	MOD_STR(MODINFO_TYPE, a, s, c)
+#define MOD_ARGS(a, s, c)	MOD_STR(MODINFO_ARGS, a, s, c)
+
+#define MOD_VAR(t, a, s, c) {			\
+    COPY32(t, a, c);				\
+    COPY32(sizeof(s), a, c);			\
+    if (c)					\
+        CALLBACK(copyin, &s, a, sizeof(s));	\
+    a += roundup(sizeof(s), sizeof(u_long));	\
+}
+
+#define MOD_ADDR(a, s, c)	MOD_VAR(MODINFO_ADDR, a, s, c)
+#define MOD_SIZE(a, s, c)	MOD_VAR(MODINFO_SIZE, a, s, c)
+
+#define MOD_METADATA(a, mm, c) {		\
+    COPY32(MODINFO_METADATA | mm->md_type, a, c); \
+    COPY32(mm->md_size, a, c);			\
+    if (c)					\
+        CALLBACK(copyin, mm->md_data, a, mm->md_size);    \
+    a += roundup(mm->md_size, sizeof(u_long));\
+}
+
+#define MOD_END(a, c) {				\
+    COPY32(MODINFO_END, a, c);			\
+    COPY32(0, a, c);				\
+}
+
+static vm_offset_t
+bi_copymodules32(vm_offset_t addr)
+{
+    struct preloaded_file	*fp;
+    struct file_metadata	*md;
+    int				c;
+
+    c = addr != 0;
+    /* start with the first module on the list, should be the kernel */
+    for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
+
+	MOD_NAME(addr, fp->f_name, c);	/* this field must come first */
+	MOD_TYPE(addr, fp->f_type, c);
+	if (fp->f_args)
+	    MOD_ARGS(addr, fp->f_args, c);
+	MOD_ADDR(addr, fp->f_addr, c);
+	MOD_SIZE(addr, fp->f_size, c);
+	for (md = fp->f_metadata; md != NULL; md = md->md_next)
+	    if (!(md->md_type & MODINFOMD_NOCOPY))
+		MOD_METADATA(addr, md, c);
+    }
+    MOD_END(addr, c);
+    return(addr);
+}
+
+/*
+ * Load the information expected by an i386 kernel.
+ *
+ * - The 'boothowto' argument is constructed
+ * - The 'bootdev' argument is constructed
+ * - The 'bootinfo' struct is constructed, and copied into the kernel space.
+ * - The kernel environment is copied into kernel space.
+ * - Module metadata are formatted and placed in kernel space.
+ */
+int
+bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp)
+{
+    struct preloaded_file	*xp, *kfp;
+    struct i386_devdesc		*rootdev;
+    struct file_metadata	*md;
+    vm_offset_t			addr;
+    vm_offset_t			kernend;
+    vm_offset_t			envp;
+    vm_offset_t			size;
+    vm_offset_t			ssym, esym;
+    char			*rootdevname;
+    int				bootdevnr, i, howto;
+    char			*kernelname;
+    const char			*kernelpath;
+
+    howto = bi_getboothowto(args);
+
+    /* 
+     * Allow the environment variable 'rootdev' to override the supplied device 
+     * This should perhaps go to MI code and/or have $rootdev tested/set by
+     * MI code before launching the kernel.
+     */
+    rootdevname = getenv("rootdev");
+    userboot_getdev((void **)(&rootdev), rootdevname, NULL);
+    if (rootdev == NULL) {		/* bad $rootdev/$currdev */
+	printf("can't determine root device\n");
+	return(EINVAL);
+    }
+
+    /* Try reading the /etc/fstab file to select the root device */
+    getrootmount(userboot_fmtdev((void *)rootdev));
+
+    bootdevnr = 0;
+#if 0
+    if (bootdevnr == -1) {
+	printf("root device %s invalid\n", i386_fmtdev(rootdev));
+	return (EINVAL);
+    }
+#endif
+    free(rootdev);
+
+    /* find the last module in the chain */
+    addr = 0;
+    for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+	if (addr < (xp->f_addr + xp->f_size))
+	    addr = xp->f_addr + xp->f_size;
+    }
+    /* pad to a page boundary */
+    addr = roundup(addr, PAGE_SIZE);
+
+    /* copy our environment */
+    envp = addr;
+    addr = bi_copyenv(addr);
+
+    /* pad to a page boundary */
+    addr = roundup(addr, PAGE_SIZE);
+
+    kfp = file_findfile(NULL, "elf kernel");
+    if (kfp == NULL)
+      kfp = file_findfile(NULL, "elf32 kernel");
+    if (kfp == NULL)
+	panic("can't find kernel file");
+    kernend = 0;	/* fill it in later */
+    file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
+    file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
+    file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
+#if 0
+    bios_addsmapdata(kfp);
+#endif
+
+    /* Figure out the size and location of the metadata */
+    *modulep = addr;
+    size = bi_copymodules32(0);
+    kernend = roundup(addr + size, PAGE_SIZE);
+    *kernendp = kernend;
+
+    /* patch MODINFOMD_KERNEND */
+    md = file_findmetadata(kfp, MODINFOMD_KERNEND);
+    bcopy(&kernend, md->md_data, sizeof kernend);
+
+    /* copy module list and metadata */
+    (void)bi_copymodules32(addr);
+
+    ssym = esym = 0;
+    md = file_findmetadata(kfp, MODINFOMD_SSYM);
+    if (md != NULL)
+	ssym = *((vm_offset_t *)&(md->md_data));
+    md = file_findmetadata(kfp, MODINFOMD_ESYM);
+    if (md != NULL)
+	esym = *((vm_offset_t *)&(md->md_data));
+    if (ssym == 0 || esym == 0)
+	ssym = esym = 0;		/* sanity */
+
+    /* legacy bootinfo structure */
+    kernelname = getenv("kernelname");
+    userboot_getdev(NULL, kernelname, &kernelpath);
+    bi.bi_version = BOOTINFO_VERSION;
+    bi.bi_kernelname = 0;		/* XXX char * -> kernel name */
+    bi.bi_nfs_diskless = 0;		/* struct nfs_diskless * */
+    bi.bi_n_bios_used = 0;		/* XXX would have to hook biosdisk driver for these */
+#if 0
+    for (i = 0; i < N_BIOS_GEOM; i++)
+        bi.bi_bios_geom[i] = bd_getbigeom(i);
+#endif
+    bi.bi_size = sizeof(bi);
+    bi.bi_memsizes_valid = 1;
+#if 0
+    bi.bi_basemem = bios_basemem / 1024;
+    bi.bi_extmem = bios_extmem / 1024;
+#endif
+    bi.bi_envp = envp;
+    bi.bi_modulep = *modulep;
+    bi.bi_kernend = kernend;
+    bi.bi_symtab = ssym;       /* XXX this is only the primary kernel symtab */
+    bi.bi_esymtab = esym;
+
+    /*
+     * Copy the legacy bootinfo and kernel name to the guest at 0x2000
+     */
+    bi.bi_kernelname = (char *) (0x2000 + sizeof(bi));
+    CALLBACK(copyin, &bi, 0x2000, sizeof(bi));
+    CALLBACK(copyin, kernelname, 0x2000 + sizeof(bi), strlen(kernelname) + 1);
+
+    /* legacy boot arguments */
+    *howtop = howto | RB_BOOTINFO;
+    *bootdevp = bootdevnr;
+    *bip = 0x2000;
+
+    return(0);
+}
diff --git a/sys/boot/userboot/userboot/bootinfo64.c b/sys/boot/userboot/userboot/bootinfo64.c
new file mode 100644
index 0000000..fc7c14d
--- /dev/null
+++ b/sys/boot/userboot/userboot/bootinfo64.c
@@ -0,0 +1,304 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bootstrap.h"
+#include "libuserboot.h"
+
+/*
+ * Copy module-related data into the load area, where it can be
+ * used as a directory for loaded modules.
+ *
+ * Module data is presented in a self-describing format.  Each datum
+ * is preceded by a 32-bit identifier and a 32-bit size field.
+ *
+ * Currently, the following data are saved:
+ *
+ * MOD_NAME	(variable)		module name (string)
+ * MOD_TYPE	(variable)		module type (string)
+ * MOD_ARGS	(variable)		module parameters (string)
+ * MOD_ADDR	sizeof(vm_offset_t)	module load address
+ * MOD_SIZE	sizeof(size_t)		module size
+ * MOD_METADATA	(variable)		type-specific metadata
+ */
+#define COPY32(v, a, c) {			\
+    u_int32_t	x = (v);			\
+    if (c)					\
+        CALLBACK(copyin, &x, a, sizeof(x));	\
+    a += sizeof(x);				\
+}
+
+#define MOD_STR(t, a, s, c) {			\
+    COPY32(t, a, c);				\
+    COPY32(strlen(s) + 1, a, c);		\
+    if (c)					\
+        CALLBACK(copyin, s, a, strlen(s) + 1);  \
+    a += roundup(strlen(s) + 1, sizeof(u_int64_t));\
+}
+
+#define MOD_NAME(a, s, c)	MOD_STR(MODINFO_NAME, a, s, c)
+#define MOD_TYPE(a, s, c)	MOD_STR(MODINFO_TYPE, a, s, c)
+#define MOD_ARGS(a, s, c)	MOD_STR(MODINFO_ARGS, a, s, c)
+
+#define MOD_VAR(t, a, s, c) {			\
+    COPY32(t, a, c);				\
+    COPY32(sizeof(s), a, c);			\
+    if (c)					\
+        CALLBACK(copyin, &s, a, sizeof(s));	\
+    a += roundup(sizeof(s), sizeof(u_int64_t));	\
+}
+
+#define MOD_ADDR(a, s, c)	MOD_VAR(MODINFO_ADDR, a, s, c)
+#define MOD_SIZE(a, s, c)	MOD_VAR(MODINFO_SIZE, a, s, c)
+
+#define MOD_METADATA(a, mm, c) {		\
+    COPY32(MODINFO_METADATA | mm->md_type, a, c); \
+    COPY32(mm->md_size, a, c);			\
+    if (c)					\
+        CALLBACK(copyin, mm->md_data, a, mm->md_size);    \
+    a += roundup(mm->md_size, sizeof(u_int64_t));\
+}
+
+#define MOD_END(a, c) {				\
+    COPY32(MODINFO_END, a, c);			\
+    COPY32(0, a, c);				\
+}
+
+static vm_offset_t
+bi_copymodules64(vm_offset_t addr)
+{
+    struct preloaded_file	*fp;
+    struct file_metadata	*md;
+    int				c;
+    u_int64_t			v;
+
+    c = addr != 0;
+    /* start with the first module on the list, should be the kernel */
+    for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
+
+	MOD_NAME(addr, fp->f_name, c);	/* this field must come first */
+	MOD_TYPE(addr, fp->f_type, c);
+	if (fp->f_args)
+	    MOD_ARGS(addr, fp->f_args, c);
+	v = fp->f_addr;
+	MOD_ADDR(addr, v, c);
+	v = fp->f_size;
+	MOD_SIZE(addr, v, c);
+	for (md = fp->f_metadata; md != NULL; md = md->md_next)
+	    if (!(md->md_type & MODINFOMD_NOCOPY))
+		MOD_METADATA(addr, md, c);
+    }
+    MOD_END(addr, c);
+    return(addr);
+}
+
+/*
+ * Check to see if this CPU supports long mode.
+ */
+static int
+bi_checkcpu(void)
+{
+#if 0
+    char *cpu_vendor;
+    int vendor[3];
+    int eflags, regs[4];
+
+    /* Check for presence of "cpuid". */
+    eflags = read_eflags();
+    write_eflags(eflags ^ PSL_ID);
+    if (!((eflags ^ read_eflags()) & PSL_ID))
+	return (0);
+
+    /* Fetch the vendor string. */
+    do_cpuid(0, regs);
+    vendor[0] = regs[1];
+    vendor[1] = regs[3];
+    vendor[2] = regs[2];
+    cpu_vendor = (char *)vendor;
+
+    /* Check for vendors that support AMD features. */
+    if (strncmp(cpu_vendor, INTEL_VENDOR_ID, 12) != 0 &&
+	strncmp(cpu_vendor, AMD_VENDOR_ID, 12) != 0 &&
+	strncmp(cpu_vendor, CENTAUR_VENDOR_ID, 12) != 0)
+	return (0);
+
+    /* Has to support AMD features. */
+    do_cpuid(0x80000000, regs);
+    if (!(regs[0] >= 0x80000001))
+	return (0);
+
+    /* Check for long mode. */
+    do_cpuid(0x80000001, regs);
+    return (regs[3] & AMDID_LM);
+#else
+	return (1);
+#endif
+}
+
+struct smap {
+        uint64_t       base;
+        uint64_t       length;
+        uint32_t       type;
+} __packed;
+
+/* From FreeBSD  */
+#define SMAP_TYPE_MEMORY	1
+
+#define GB (1024UL * 1024 * 1024)
+
+#define MODINFOMD_SMAP          0x1001
+
+static void
+bios_addsmapdata(struct preloaded_file *kfp)
+{
+	uint64_t lowmem, highmem;
+	int smapnum, len;
+	struct smap smap[3], *sm;
+
+	CALLBACK(getmem, &lowmem, &highmem);
+
+	sm = &smap[0];
+
+	sm->base = 0;				/* base memory */
+	sm->length = 640 * 1024;
+	sm->type = SMAP_TYPE_MEMORY;
+	sm++;
+
+	sm->base = 0x100000;			/* extended memory */
+	sm->length = lowmem - 0x100000;
+	sm->type = SMAP_TYPE_MEMORY;
+	sm++;
+
+	smapnum = 2;
+
+        if (highmem != 0) {
+                sm->base = 4 * GB;
+                sm->length = highmem;
+                sm->type = SMAP_TYPE_MEMORY;
+		smapnum++;
+        }
+
+        len = smapnum * sizeof (struct smap);
+        file_addmetadata(kfp, MODINFOMD_SMAP, len, &smap[0]);
+}
+
+/*
+ * Load the information expected by an amd64 kernel.
+ *
+ * - The 'boothowto' argument is constructed
+ * - The 'bootdev' argument is constructed
+ * - The 'bootinfo' struct is constructed, and copied into the kernel space.
+ * - The kernel environment is copied into kernel space.
+ * - Module metadata are formatted and placed in kernel space.
+ */
+int
+bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
+{
+    struct preloaded_file	*xp, *kfp;
+    struct userboot_devdesc	*rootdev;
+    struct file_metadata	*md;
+    vm_offset_t			addr;
+    u_int64_t			kernend;
+    u_int64_t			envp;
+    vm_offset_t			size;
+    char			*rootdevname;
+    int				howto;
+
+    if (!bi_checkcpu()) {
+	printf("CPU doesn't support long mode\n");
+	return (EINVAL);
+    }
+
+    howto = bi_getboothowto(args);
+
+    /* 
+     * Allow the environment variable 'rootdev' to override the supplied device 
+     * This should perhaps go to MI code and/or have $rootdev tested/set by
+     * MI code before launching the kernel.
+     */
+    rootdevname = getenv("rootdev");
+    userboot_getdev((void **)(&rootdev), rootdevname, NULL);
+    if (rootdev == NULL) {		/* bad $rootdev/$currdev */
+	printf("can't determine root device\n");
+	return(EINVAL);
+    }
+
+    /* Try reading the /etc/fstab file to select the root device */
+    getrootmount(userboot_fmtdev((void *)rootdev));
+
+    /* find the last module in the chain */
+    addr = 0;
+    for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+	if (addr < (xp->f_addr + xp->f_size))
+	    addr = xp->f_addr + xp->f_size;
+    }
+    /* pad to a page boundary */
+    addr = roundup(addr, PAGE_SIZE);
+
+    /* copy our environment */
+    envp = addr;
+    addr = bi_copyenv(addr);
+
+    /* pad to a page boundary */
+    addr = roundup(addr, PAGE_SIZE);
+
+    kfp = file_findfile(NULL, "elf kernel");
+    if (kfp == NULL)
+      kfp = file_findfile(NULL, "elf64 kernel");
+    if (kfp == NULL)
+	panic("can't find kernel file");
+    kernend = 0;	/* fill it in later */
+    file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
+    file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
+    file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
+    bios_addsmapdata(kfp);
+
+    /* Figure out the size and location of the metadata */
+    *modulep = addr;
+    size = bi_copymodules64(0);
+    kernend = roundup(addr + size, PAGE_SIZE);
+    *kernendp = kernend;
+
+    /* patch MODINFOMD_KERNEND */
+    md = file_findmetadata(kfp, MODINFOMD_KERNEND);
+    bcopy(&kernend, md->md_data, sizeof kernend);
+
+    /* copy module list and metadata */
+    (void)bi_copymodules64(addr);
+
+    return(0);
+}
diff --git a/sys/boot/userboot/userboot/conf.c b/sys/boot/userboot/userboot/conf.c
new file mode 100644
index 0000000..0c57eba
--- /dev/null
+++ b/sys/boot/userboot/userboot/conf.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1997
+ *	Matthias Drochner.  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 for the NetBSD Project
+ *	by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ *	$NetBSD: conf.c,v 1.2 1997/03/22 09:03:29 thorpej Exp $	 
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+
+#include "libuserboot.h"
+
+/*
+ * We could use linker sets for some or all of these, but
+ * then we would have to control what ended up linked into
+ * the bootstrap.  So it's easier to conditionalise things
+ * here.
+ *
+ * XXX rename these arrays to be consistent and less namespace-hostile
+ */
+
+/* Exported for libstand */
+struct devsw *devsw[] = {
+	&host_dev,
+	&userboot_disk,
+	NULL
+};
+
+struct fs_ops *file_system[] = {
+	&host_fsops,
+	&ufs_fsops,
+	&gzipfs_fsops,
+	NULL
+};
+
+/* Exported for i386 only */
+/* 
+ * Sort formats so that those that can detect based on arguments
+ * rather than reading the file go first.
+ */
+extern struct file_format	i386_elf;
+extern struct file_format	i386_elf_obj;
+extern struct file_format	amd64_elf;
+extern struct file_format	amd64_elf_obj;
+
+struct file_format *file_formats[] = {
+    &i386_elf,
+    &i386_elf_obj,
+    &amd64_elf,
+    &amd64_elf_obj,
+    NULL
+};
+
+/* 
+ * Consoles 
+ *
+ * We don't prototype these in libuserboot.h because they require
+ * data structures from bootstrap.h as well.
+ */
+extern struct console userboot_console;
+
+struct console *consoles[] = {
+	&userboot_console,
+	NULL
+};
diff --git a/sys/boot/userboot/userboot/copy.c b/sys/boot/userboot/userboot/copy.c
new file mode 100644
index 0000000..94548f2
--- /dev/null
+++ b/sys/boot/userboot/userboot/copy.c
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+
+#include "libuserboot.h"
+
+ssize_t
+userboot_copyin(const void *src, vm_offset_t va, size_t len)
+{
+
+        CALLBACK(copyin, src, va, len);
+	return (len);
+}
+
+ssize_t
+userboot_copyout(vm_offset_t va, void *dst, size_t len)
+{
+
+	CALLBACK(copyout, va, dst, len);
+	return (len);
+}
+
+ssize_t
+userboot_readin(int fd, vm_offset_t va, size_t len)
+{
+	void *pa;
+	ssize_t res, s;
+	size_t sz;
+	char buf[4096];
+
+	res = 0;
+	while (len > 0) {
+		sz = len;
+		if (sz > sizeof(buf))
+			sz = sizeof(buf);
+		s = read(fd, buf, sz);
+		if (s == 0)
+			break;
+		if (s < 0)
+			return (s);
+		CALLBACK(copyin, buf, va, s);
+		len -= s;
+		res += s;
+		va += s;
+	}
+	return (res);
+}
diff --git a/sys/boot/userboot/userboot/devicename.c b/sys/boot/userboot/userboot/devicename.c
new file mode 100644
index 0000000..24c5179
--- /dev/null
+++ b/sys/boot/userboot/userboot/devicename.c
@@ -0,0 +1,274 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+
+#include "bootstrap.h"
+#include "disk.h"
+#include "libuserboot.h"
+
+static int	userboot_parsedev(struct disk_devdesc **dev, const char *devspec, const char **path);
+
+/* 
+ * Point (dev) at an allocated device specifier for the device matching the
+ * path in (devspec). If it contains an explicit device specification,
+ * use that.  If not, use the default device.
+ */
+int
+userboot_getdev(void **vdev, const char *devspec, const char **path)
+{
+    struct disk_devdesc **dev = (struct disk_devdesc **)vdev;
+    int				rv;
+    
+    /*
+     * If it looks like this is just a path and no
+     * device, go with the current device.
+     */
+    if ((devspec == NULL) || 
+	(devspec[0] == '/') || 
+	(strchr(devspec, ':') == NULL)) {
+
+	if (((rv = userboot_parsedev(dev, getenv("currdev"), NULL)) == 0) &&
+	    (path != NULL))
+		*path = devspec;
+	return(rv);
+    }
+    
+    /*
+     * Try to parse the device name off the beginning of the devspec
+     */
+    return(userboot_parsedev(dev, devspec, path));
+}
+
+/*
+ * Point (dev) at an allocated device specifier matching the string version
+ * at the beginning of (devspec).  Return a pointer to the remaining
+ * text in (path).
+ *
+ * In all cases, the beginning of (devspec) is compared to the names
+ * of known devices in the device switch, and then any following text
+ * is parsed according to the rules applied to the device type.
+ *
+ * For disk-type devices, the syntax is:
+ *
+ * disk[s][]:
+ * 
+ */
+static int
+userboot_parsedev(struct disk_devdesc **dev, const char *devspec, const char **path)
+{
+    struct disk_devdesc *idev;
+    struct devsw	*dv;
+    int			i, unit, slice, partition, err;
+    char		*cp;
+    const char		*np;
+
+    /* minimum length check */
+    if (strlen(devspec) < 2)
+	return(EINVAL);
+
+    /* look for a device that matches */
+    for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
+	if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) {
+	    dv = devsw[i];
+	    break;
+	}
+    }
+    if (dv == NULL)
+	return(ENOENT);
+    idev = malloc(sizeof(struct disk_devdesc));
+    err = 0;
+    np = (devspec + strlen(dv->dv_name));
+        
+    switch(dv->dv_type) {
+    case DEVT_NONE:			/* XXX what to do here?  Do we care? */
+	break;
+
+    case DEVT_DISK:
+	unit = -1;
+	slice = -1;
+	partition = -1;
+	if (*np && (*np != ':')) {
+	    unit = strtol(np, &cp, 10);	/* next comes the unit number */
+	    if (cp == np) {
+		err = EUNIT;
+		goto fail;
+	    }
+#ifdef LOADER_GPT_SUPPORT
+	    if (*cp == 'p') {		/* got a GPT partition */
+		np = cp + 1;
+		slice = strtol(np, &cp, 10);
+		if (cp == np) {
+		    err = ESLICE;
+		    goto fail;
+		}
+		if (*cp && (*cp != ':')) {
+		    err = EINVAL;
+		    goto fail;
+		}
+		partition = 0xff;
+	    } else {
+#endif
+		if (*cp == 's') {		/* got a slice number */
+		    np = cp + 1;
+		    slice = strtol(np, &cp, 10);
+		    if (cp == np) {
+			err = ESLICE;
+			goto fail;
+		    }
+		}
+		if (*cp && (*cp != ':')) {
+		    partition = *cp - 'a';	/* got a partition number */
+		    if ((partition < 0) || (partition >= MAXPARTITIONS)) {
+			err = EPART;
+			goto fail;
+		    }
+		    cp++;
+		}
+#ifdef LOADER_GPT_SUPPORT
+	    }
+#endif
+	} else {
+		cp = np;
+	}
+	if (*cp && (*cp != ':')) {
+	    err = EINVAL;
+	    goto fail;
+	}
+
+	idev->d_unit = unit;
+	idev->d_slice = slice;
+	idev->d_partition = partition;
+	if (path != NULL)
+	    *path = (*cp == 0) ? cp : cp + 1;
+	break;
+
+    case DEVT_CD:
+    case DEVT_NET:
+    case DEVT_ZFS:
+	unit = 0;
+
+	if (*np && (*np != ':')) {
+	    unit = strtol(np, &cp, 0);	/* get unit number if present */
+	    if (cp == np) {
+		err = EUNIT;
+		goto fail;
+	    }
+	} else {
+		cp = np;
+	}
+	if (*cp && (*cp != ':')) {
+	    err = EINVAL;
+	    goto fail;
+	}
+
+	idev->d_unit = unit;
+	if (path != NULL)
+	    *path = (*cp == 0) ? cp : cp + 1;
+	break;
+
+    default:
+	err = EINVAL;
+	goto fail;
+    }
+    idev->d_dev = dv;
+    idev->d_type = dv->dv_type;
+    if (dev == NULL) {
+	free(idev);
+    } else {
+	*dev = idev;
+    }
+    return(0);
+
+ fail:
+    free(idev);
+    return(err);
+}
+
+
+char *
+userboot_fmtdev(void *vdev)
+{
+    struct disk_devdesc	*dev = (struct disk_devdesc *)vdev;
+    static char		buf[128];	/* XXX device length constant? */
+    char		*cp;
+    
+    switch(dev->d_type) {
+    case DEVT_NONE:
+	strcpy(buf, "(no device)");
+	break;
+
+    case DEVT_CD:
+	sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
+	break;
+
+    case DEVT_DISK:
+	cp = buf;
+	cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_unit);
+#ifdef LOADER_GPT_SUPPORT
+	if (dev->d_partition == 0xff) {
+	    cp += sprintf(cp, "p%d", dev->d_slice);
+	} else {
+#endif
+	    if (dev->d_slice > 0)
+		cp += sprintf(cp, "s%d", dev->d_slice);
+	    if (dev->d_partition >= 0)
+		cp += sprintf(cp, "%c", dev->d_partition + 'a');
+#ifdef LOADER_GPT_SUPPORT
+	}
+#endif
+	strcat(cp, ":");
+	break;
+
+    case DEVT_NET:
+    case DEVT_ZFS:
+	sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
+	break;
+    }
+    return(buf);
+}
+
+
+/*
+ * Set currdev to suit the value being supplied in (value)
+ */
+int
+userboot_setcurrdev(struct env_var *ev, int flags, const void *value)
+{
+    struct disk_devdesc	*ncurr;
+    int			rv;
+
+    if ((rv = userboot_parsedev(&ncurr, value, NULL)) != 0)
+	return(rv);
+    free(ncurr);
+    env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+    return(0);
+}
diff --git a/sys/boot/userboot/userboot/elf32_freebsd.c b/sys/boot/userboot/userboot/elf32_freebsd.c
new file mode 100644
index 0000000..8489385
--- /dev/null
+++ b/sys/boot/userboot/userboot/elf32_freebsd.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bootstrap.h"
+#include "libuserboot.h"
+
+static int	elf32_exec(struct preloaded_file *amp);
+static int	elf32_obj_exec(struct preloaded_file *amp);
+
+struct file_format i386_elf = { elf32_loadfile, elf32_exec };
+struct file_format i386_elf_obj = { elf32_obj_loadfile, elf32_obj_exec };
+
+/*
+ * There is an ELF kernel and one or more ELF modules loaded.  
+ * We wish to start executing the kernel image, so make such 
+ * preparations as are required, and do so.
+ */
+static int
+elf32_exec(struct preloaded_file *fp)
+{
+	struct file_metadata	*md;
+	Elf_Ehdr 		*ehdr;
+	vm_offset_t		entry, bootinfop, modulep, kernend;
+	int			boothowto, err, bootdev;
+	uint32_t		stack[1024];
+
+
+	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
+		return(EFTYPE);
+	ehdr = (Elf_Ehdr *)&(md->md_data);
+
+	err = bi_load32(fp->f_args, &boothowto, &bootdev, &bootinfop, &modulep, &kernend);
+	if (err != 0)
+		return(err);
+	entry = ehdr->e_entry & 0xffffff;
+
+#ifdef DEBUG
+	printf("Start @ 0x%lx ...\n", entry);
+#endif
+
+	dev_cleanup();
+
+	/*
+	 * Build a scratch stack at physical 0x1000
+	 */
+	stack[0] = boothowto;
+	stack[1] = bootdev;
+	stack[2] = 0;
+	stack[3] = 0;
+	stack[4] = 0;
+	stack[5] = bootinfop;
+	stack[6] = modulep;
+	stack[7] = kernend;
+	CALLBACK(copyin, stack, 0x1000, sizeof(stack));
+	CALLBACK(setreg, 4, 0x1000);
+        CALLBACK(exec, entry);
+
+	panic("exec returned");
+}
+
+static int
+elf32_obj_exec(struct preloaded_file *fp)
+{
+	return (EFTYPE);
+}
diff --git a/sys/boot/userboot/userboot/elf64_freebsd.c b/sys/boot/userboot/userboot/elf64_freebsd.c
new file mode 100644
index 0000000..36129ef
--- /dev/null
+++ b/sys/boot/userboot/userboot/elf64_freebsd.c
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#define __ELF_WORD_SIZE 64
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bootstrap.h"
+#include "libuserboot.h"
+
+static int	elf64_exec(struct preloaded_file *amp);
+static int	elf64_obj_exec(struct preloaded_file *amp);
+
+struct file_format amd64_elf = { elf64_loadfile, elf64_exec };
+struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
+
+#define MSR_EFER        0xc0000080
+#define EFER_LME        0x00000100
+#define	EFER_LMA 	0x00000400	/* Long mode active (R) */
+#define CR4_PAE         0x00000020
+#define	CR4_VMXE	(1UL << 13)
+#define CR4_PSE         0x00000010
+#define CR0_PG          0x80000000
+#define	CR0_PE		0x00000001	/* Protected mode Enable */
+#define	CR0_NE		0x00000020	/* Numeric Error enable (EX16 vs IRQ13) */
+
+#define PG_V	0x001
+#define PG_RW	0x002
+#define PG_U	0x004
+#define PG_PS	0x080
+
+typedef u_int64_t p4_entry_t;
+typedef u_int64_t p3_entry_t;
+typedef u_int64_t p2_entry_t;
+
+#define	GUEST_NULL_SEL		0
+#define	GUEST_CODE_SEL		1
+#define	GUEST_DATA_SEL		2
+#define	GUEST_GDTR_LIMIT	(3 * 8 - 1)
+
+static void
+setup_freebsd_gdt(uint64_t *gdtr)
+{
+	gdtr[GUEST_NULL_SEL] = 0;
+	gdtr[GUEST_CODE_SEL] = 0x0020980000000000;
+	gdtr[GUEST_DATA_SEL] = 0x0000900000000000;
+}
+
+/*
+ * There is an ELF kernel and one or more ELF modules loaded.
+ * We wish to start executing the kernel image, so make such
+ * preparations as are required, and do so.
+ */
+static int
+elf64_exec(struct preloaded_file *fp)
+{
+	struct file_metadata	*md;
+	Elf_Ehdr 		*ehdr;
+	vm_offset_t		modulep, kernend;
+	int			err;
+	int			i;
+	uint32_t		stack[1024];
+	p4_entry_t		PT4[512];
+	p3_entry_t		PT3[512];
+	p2_entry_t		PT2[512];
+	uint64_t		gdtr[3];
+
+	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
+		return(EFTYPE);
+	ehdr = (Elf_Ehdr *)&(md->md_data);
+
+	err = bi_load64(fp->f_args, &modulep, &kernend);
+	if (err != 0)
+		return(err);
+
+	bzero(PT4, PAGE_SIZE);
+	bzero(PT3, PAGE_SIZE);
+	bzero(PT2, PAGE_SIZE);
+
+	/*
+	 * Build a scratch stack at physical 0x1000, page tables:
+	 *	PT4 at 0x2000,
+	 *	PT3 at 0x3000,
+	 *	PT2 at 0x4000,
+	 *      gdtr at 0x5000,
+	 */
+
+	/*
+	 * This is kinda brutal, but every single 1GB VM memory segment
+	 * points to the same first 1GB of physical memory.  But it is
+	 * more than adequate.
+	 */
+	for (i = 0; i < 512; i++) {
+		/* Each slot of the level 4 pages points to the same level 3 page */
+		PT4[i] = (p4_entry_t) 0x3000;
+		PT4[i] |= PG_V | PG_RW | PG_U;
+
+		/* Each slot of the level 3 pages points to the same level 2 page */
+		PT3[i] = (p3_entry_t) 0x4000;
+		PT3[i] |= PG_V | PG_RW | PG_U;
+
+		/* The level 2 page slots are mapped with 2MB pages for 1GB. */
+		PT2[i] = i * (2 * 1024 * 1024);
+		PT2[i] |= PG_V | PG_RW | PG_PS | PG_U;
+	}
+
+#ifdef DEBUG
+	printf("Start @ %#llx ...\n", ehdr->e_entry);
+#endif
+
+	dev_cleanup();
+
+	stack[0] = 0;		/* return address */;
+	stack[1] = modulep;
+	stack[2] = kernend;
+	CALLBACK(copyin, stack, 0x1000, sizeof(stack));
+	CALLBACK(copyin, PT4, 0x2000, sizeof(PT4));
+	CALLBACK(copyin, PT3, 0x3000, sizeof(PT3));
+	CALLBACK(copyin, PT2, 0x4000, sizeof(PT2));
+	CALLBACK(setreg, 4, 0x1000);
+
+	CALLBACK(setmsr, MSR_EFER, EFER_LMA | EFER_LME);
+	CALLBACK(setcr, 4, CR4_PAE | CR4_VMXE);
+	CALLBACK(setcr, 3, 0x2000);
+	CALLBACK(setcr, 0, CR0_PG | CR0_PE | CR0_NE);
+
+	setup_freebsd_gdt(gdtr);
+	CALLBACK(copyin, gdtr, 0x5000, sizeof(gdtr));
+        CALLBACK(setgdt, 0x5000, sizeof(gdtr));
+
+	CALLBACK(exec, ehdr->e_entry);
+
+	panic("exec returned");
+}
+
+static int
+elf64_obj_exec(struct preloaded_file *fp)
+{
+
+	return (EFTYPE);
+}
diff --git a/sys/boot/userboot/userboot/host.c b/sys/boot/userboot/userboot/host.c
new file mode 100644
index 0000000..81858a9
--- /dev/null
+++ b/sys/boot/userboot/userboot/host.c
@@ -0,0 +1,198 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+/*
+ * Read from the host filesystem
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "libuserboot.h"
+
+/*
+ * Open a file.
+ */
+static int
+host_open(const char *upath, struct open_file *f)
+{
+
+	if (f->f_dev != &host_dev)
+		return (EINVAL);
+
+	return (CALLBACK(open, upath, &f->f_fsdata));
+}
+
+static int
+host_close(struct open_file *f)
+{
+
+        CALLBACK(close, f->f_fsdata);
+	f->f_fsdata = (void *)0;
+
+	return (0);
+}
+
+/*
+ * Copy a portion of a file into memory.
+ */
+static int
+host_read(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+	return (CALLBACK(read, f->f_fsdata, start, size, resid));
+}
+
+/*
+ * Don't be silly - the bootstrap has no business writing anything.
+ */
+static int
+host_write(struct open_file *f, void *start, size_t size, size_t *resid)
+{
+
+	return (EROFS);
+}
+
+static off_t
+host_seek(struct open_file *f, off_t offset, int where)
+{
+
+	return (CALLBACK(seek, f->f_fsdata, offset, where));
+}
+
+static int
+host_stat(struct open_file *f, struct stat *sb)
+{
+	int mode;
+	int uid;
+	int gid;
+	uint64_t size;
+
+	CALLBACK(stat, f->f_fsdata, &mode, &uid, &gid, &size);
+	sb->st_mode = mode;
+	sb->st_uid = uid;
+	sb->st_gid = gid;
+	sb->st_size = size;
+	return (0);
+}
+
+static int
+host_readdir(struct open_file *f, struct dirent *d)
+{
+	uint32_t fileno;
+	uint8_t type;
+	size_t namelen;
+	int rc;
+
+	rc = CALLBACK(readdir, f->f_fsdata, &fileno, &type, &namelen,
+            d->d_name);
+	if (rc)
+		return (rc);
+
+	d->d_fileno = fileno;
+	d->d_type = type;
+	d->d_namlen = namelen;
+
+	return (0);
+}
+
+static int
+host_dev_init(void)
+{
+
+	return (0);
+}
+
+static void
+host_dev_print(int verbose)
+{
+	char line[80];
+
+	sprintf(line, "    host%d:   Host filesystem\n", 0);
+	pager_output(line);
+}
+
+/*
+ * 'Open' the host device.
+ */
+static int
+host_dev_open(struct open_file *f, ...)
+{
+	va_list		args;
+	struct devdesc	*dev;
+
+	va_start(args, f);
+	dev = va_arg(args, struct devdesc*);
+	va_end(args);
+
+	return (0);
+}
+
+static int
+host_dev_close(struct open_file *f)
+{
+
+	return (0);
+}
+
+static int
+host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
+    char *buf, size_t *rsize)
+{
+
+	return (ENOSYS);
+}
+
+struct fs_ops host_fsops = {
+	"host",
+	host_open,
+	host_close,
+	host_read,
+	host_write,
+	host_seek,
+	host_stat,
+	host_readdir
+};
+
+struct devsw host_dev = {
+	.dv_name = "host",
+	.dv_type = DEVT_NET,
+	.dv_init = host_dev_init,
+	.dv_strategy = host_dev_strategy,
+	.dv_open = host_dev_open,
+	.dv_close = host_dev_close,
+	.dv_ioctl = noioctl,
+	.dv_print = host_dev_print,
+	.dv_cleanup = NULL
+};
diff --git a/sys/boot/userboot/userboot/libuserboot.h b/sys/boot/userboot/userboot/libuserboot.h
new file mode 100644
index 0000000..0aa1a3f
--- /dev/null
+++ b/sys/boot/userboot/userboot/libuserboot.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "userboot.h"
+
+extern struct loader_callbacks_v1 *callbacks;
+extern void *callbacks_arg;
+
+#define	CALLBACK(fn, args...) (callbacks->fn(callbacks_arg , ##args))
+
+#define	MAXDEV	31	/* maximum number of distinct devices */
+
+typedef unsigned long physaddr_t;
+
+/* exported devices */
+extern struct devsw userboot_disk;
+extern int userboot_disk_maxunit;
+extern struct devsw host_dev;
+
+/* access to host filesystem */
+struct fs_ops host_fsops;
+
+struct bootinfo;
+struct preloaded_file;
+extern int		bi_load(struct bootinfo *, struct preloaded_file *);
+
+extern void delay(int);
+
+extern int userboot_autoload(void);
+extern ssize_t userboot_copyin(const void *, vm_offset_t, size_t);
+extern ssize_t userboot_copyout(vm_offset_t, void *, size_t);
+extern ssize_t userboot_readin(int, vm_offset_t, size_t);
+extern int userboot_getdev(void **, const char *, const char **);
+char	*userboot_fmtdev(void *vdev);
+int	userboot_setcurrdev(struct env_var *ev, int flags, const void *value);
+
+int	bi_getboothowto(char *kargs);
+void	bi_setboothowto(int howto);
+vm_offset_t	bi_copyenv(vm_offset_t addr);
+int	bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
+    vm_offset_t *modulep, vm_offset_t *kernend);
+int	bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend);
diff --git a/sys/boot/userboot/userboot/main.c b/sys/boot/userboot/userboot/main.c
new file mode 100644
index 0000000..d01d95e
--- /dev/null
+++ b/sys/boot/userboot/userboot/main.c
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 1998 Michael Smith 
+ * Copyright (c) 1998,2000 Doug Rabson 
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include 
+#include 
+
+#include "bootstrap.h"
+#include "disk.h"
+#include "libuserboot.h"
+
+struct loader_callbacks_v1 *callbacks;
+void *callbacks_arg;
+
+extern char bootprog_name[];
+extern char bootprog_rev[];
+extern char bootprog_date[];
+extern char bootprog_maker[];
+static jmp_buf jb;
+
+struct arch_switch archsw;	/* MI/MD interface boundary */
+
+static void	extract_currdev(void);
+
+void
+delay(int usec)
+{
+
+        CALLBACK(delay, usec);
+}
+
+void
+exit(int v)
+{
+
+	CALLBACK(exit, v);
+	longjmp(jb, 1);
+}
+
+void
+loader_main(struct loader_callbacks_v1 *cb, void *arg, int version, int ndisks)
+{
+	static char malloc[512*1024];
+	int i;
+
+        if (version != USERBOOT_VERSION_1)
+                abort();
+
+	callbacks = cb;
+        callbacks_arg = arg;
+	userboot_disk_maxunit = ndisks;
+
+	/*
+	 * initialise the heap as early as possible.  Once this is done,
+	 * alloc() is usable. The stack is buried inside us, so this is
+	 * safe.
+	 */
+	setheap((void *)malloc, (void *)(malloc + 512*1024));
+
+        /*
+         * Hook up the console
+         */
+	cons_probe();
+
+	/*
+	 * March through the device switch probing for things.
+	 */
+	for (i = 0; devsw[i] != NULL; i++)
+		if (devsw[i]->dv_init != NULL)
+			(devsw[i]->dv_init)();
+
+	printf("\n");
+	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
+	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
+#if 0
+	printf("Memory: %ld k\n", memsize() / 1024);
+#endif
+
+	setenv("LINES", "24", 1);	/* optional */
+
+	archsw.arch_autoload = userboot_autoload;
+	archsw.arch_getdev = userboot_getdev;
+	archsw.arch_copyin = userboot_copyin;
+	archsw.arch_copyout = userboot_copyout;
+	archsw.arch_readin = userboot_readin;
+
+	extract_currdev();
+
+	if (setjmp(jb))
+		return;
+
+	interact();			/* doesn't return */
+
+	exit(0);
+}
+
+/*
+ * Set the 'current device' by (if possible) recovering the boot device as 
+ * supplied by the initial bootstrap.
+ */
+static void
+extract_currdev(void)
+{
+	struct disk_devdesc dev;
+
+	//bzero(&dev, sizeof(dev));
+
+	if (userboot_disk_maxunit > 0) {
+		dev.d_dev = &userboot_disk;
+		dev.d_type = dev.d_dev->dv_type;
+		dev.d_unit = 0;
+		dev.d_slice = 0;
+		dev.d_partition = 0;
+		/*
+		 * Figure out if we are using MBR or GPT - for GPT we
+		 * set the partition to 0 since everything is a GPT slice.
+		 */
+		if (dev.d_dev->dv_open(NULL, &dev))
+			dev.d_partition = 255;
+	} else {
+		dev.d_dev = &host_dev;
+		dev.d_type = dev.d_dev->dv_type;
+		dev.d_unit = 0;
+	}
+
+	env_setenv("currdev", EV_VOLATILE, userboot_fmtdev(&dev),
+            userboot_setcurrdev, env_nounset);
+	env_setenv("loaddev", EV_VOLATILE, userboot_fmtdev(&dev),
+            env_noset, env_nounset);
+}
+
+COMMAND_SET(quit, "quit", "exit the loader", command_quit);
+
+static int
+command_quit(int argc, char *argv[])
+{
+
+	exit(USERBOOT_EXIT_QUIT);
+	return (CMD_OK);
+}
+
+COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
+
+static int
+command_reboot(int argc, char *argv[])
+{
+
+	exit(USERBOOT_EXIT_REBOOT);
+	return (CMD_OK);
+}
diff --git a/sys/boot/userboot/userboot/userboot_cons.c b/sys/boot/userboot/userboot/userboot_cons.c
new file mode 100644
index 0000000..5ecb7c8
--- /dev/null
+++ b/sys/boot/userboot/userboot/userboot_cons.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+#include 
+#include "bootstrap.h"
+#include "libuserboot.h"
+
+int console;
+
+static void userboot_cons_probe(struct console *cp);
+static int userboot_cons_init(int);
+static void userboot_cons_putchar(int);
+static int userboot_cons_getchar(void);
+static int userboot_cons_poll(void);
+
+struct console userboot_console = {
+	"userboot",
+	"userboot",
+	0,
+	userboot_cons_probe,
+	userboot_cons_init,
+	userboot_cons_putchar,
+	userboot_cons_getchar,
+	userboot_cons_poll,
+};
+
+static void
+userboot_cons_probe(struct console *cp)
+{
+
+	cp->c_flags |= (C_PRESENTIN | C_PRESENTOUT);
+}
+
+static int
+userboot_cons_init(int arg)
+{
+
+	return (0);
+}
+
+static void
+userboot_cons_putchar(int c)
+{
+
+        CALLBACK(putc, c);
+}
+
+static int
+userboot_cons_getchar()
+{
+
+	return (CALLBACK(getc));
+}
+
+static int
+userboot_cons_poll()
+{
+
+	return (CALLBACK(poll));
+}
diff --git a/sys/boot/userboot/userboot/userboot_disk.c b/sys/boot/userboot/userboot/userboot_disk.c
new file mode 100644
index 0000000..074d3e1
--- /dev/null
+++ b/sys/boot/userboot/userboot/userboot_disk.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2011 Google, Inc.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#include 
+__FBSDID("$FreeBSD$");
+
+/*
+ * Userboot disk image handling.
+ */
+
+#include 
+
+#include 
+#include 
+
+#include 
+
+#include "disk.h"
+#include "libuserboot.h"
+
+int userboot_disk_maxunit = 0;
+
+static int	userdisk_init(void);
+static int	userdisk_strategy(void *devdata, int flag, daddr_t dblk,
+		    size_t size, char *buf, size_t *rsize);
+static int	userdisk_open(struct open_file *f, ...);
+static int	userdisk_close(struct open_file *f);
+static void	userdisk_print(int verbose);
+
+struct devsw userboot_disk = {
+	"disk",
+	DEVT_DISK,
+	userdisk_init,
+	userdisk_strategy,
+	userdisk_open,
+	userdisk_close,
+	noioctl,
+	userdisk_print,
+	NULL
+};
+
+/*
+ * Nothing to do here.
+ */
+static int
+userdisk_init(void)
+{
+
+	return(0);
+}
+
+/*
+ * Print information about disks
+ */
+static void
+userdisk_print(int verbose)
+{
+	int			i;
+	char			line[80];
+	struct disk_devdesc	dev;
+
+	for (i = 0; i < userboot_disk_maxunit; i++) {
+		sprintf(line, "    disk%d:   Guest drive image\n", i);
+		pager_output(line);
+		dev.d_dev = &userboot_disk;
+		dev.d_unit = i;
+		dev.d_slice = -1;
+		dev.d_partition = -1;
+		dev.d_offset = 0;
+		sprintf(line, "    disk%d", i);
+		disk_print(&dev, line, verbose);
+	}
+}
+
+/*
+ * Attempt to open the disk described by (dev) for use by (f).
+ */
+static int
+userdisk_open(struct open_file *f, ...)
+{
+	va_list			ap;
+	struct disk_devdesc	*dev;
+
+	va_start(ap, f);
+	dev = va_arg(ap, struct disk_devdesc *);
+	va_end(ap);
+
+	if (dev->d_unit < 0 || dev->d_unit >= userboot_disk_maxunit)
+		return (EIO);
+
+	return (disk_open(dev));
+}
+
+static int
+userdisk_close(struct open_file *f)
+{
+
+	return(0);
+}
+
+static int
+userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
+    char *buf, size_t *rsize)
+{
+	struct disk_devdesc *dev = devdata;
+	uint64_t	off;
+	size_t		resid;
+	int		rc;
+
+	if (rw == F_WRITE)
+		return (EROFS);
+	if (rw != F_READ)
+		return (EINVAL);
+	if (rsize)
+		*rsize = 0;
+	off = (dblk + dev->d_offset) * DISK_SECSIZE;
+	rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid);
+	if (rc)
+		return (rc);
+	if (rsize)
+		*rsize = size - resid;
+	return (0);
+}
diff --git a/sys/boot/userboot/userboot/version b/sys/boot/userboot/userboot/version
new file mode 100644
index 0000000..ce6e270
--- /dev/null
+++ b/sys/boot/userboot/userboot/version
@@ -0,0 +1,4 @@
+$FreeBSD$
+
+1.1:	Initial userland boot
+
-- 
cgit v1.1