Date: Wed, 10 Dec 2008 21:22:57 +0000 (UTC) From: Max Laier <mlaier@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r185886 - vendor-sys/pf/dist/net Message-ID: <200812102122.mBALMvpq043303@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mlaier Date: Wed Dec 10 21:22:57 2008 New Revision: 185886 URL: http://svn.freebsd.org/changeset/base/185886 Log: Import OPENBSD_4_3_BASE Modified: vendor-sys/pf/dist/net/if_pflog.c vendor-sys/pf/dist/net/if_pfsync.c vendor-sys/pf/dist/net/if_pfsync.h vendor-sys/pf/dist/net/pf.c vendor-sys/pf/dist/net/pf_if.c vendor-sys/pf/dist/net/pf_ioctl.c vendor-sys/pf/dist/net/pf_norm.c vendor-sys/pf/dist/net/pf_osfp.c vendor-sys/pf/dist/net/pf_table.c vendor-sys/pf/dist/net/pfvar.h Modified: vendor-sys/pf/dist/net/if_pflog.c ============================================================================== --- vendor-sys/pf/dist/net/if_pflog.c Wed Dec 10 21:22:15 2008 (r185885) +++ vendor-sys/pf/dist/net/if_pflog.c Wed Dec 10 21:22:57 2008 (r185886) @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pflog.c,v 1.24 2007/05/26 17:13:30 jason Exp $ */ +/* $OpenBSD: if_pflog.c,v 1.27 2007/12/20 02:53:02 brad Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -107,9 +107,9 @@ pflog_clone_create(struct if_clone *ifc, 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; ifp = &pflogif->sc_if; @@ -191,9 +191,6 @@ int pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { switch (cmd) { - case SIOCSIFADDR: - case SIOCAIFADDR: - case SIOCSIFDSTADDR: case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) ifp->if_flags |= IFF_RUNNING; @@ -201,7 +198,7 @@ pflogioctl(struct ifnet *ifp, u_long cmd ifp->if_flags &= ~IFF_RUNNING; break; default: - return (EINVAL); + return (ENOTTY); } return (0); Modified: vendor-sys/pf/dist/net/if_pfsync.c ============================================================================== --- vendor-sys/pf/dist/net/if_pfsync.c Wed Dec 10 21:22:15 2008 (r185885) +++ vendor-sys/pf/dist/net/if_pfsync.c Wed Dec 10 21:22:57 2008 (r185886) @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.83 2007/06/26 14:44:12 mcbride Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.89 2008/01/12 17:08:33 mpf Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -36,6 +36,7 @@ #include <sys/ioctl.h> #include <sys/timeout.h> #include <sys/kernel.h> +#include <sys/sysctl.h> #include <net/if.h> #include <net/if_types.h> @@ -45,6 +46,7 @@ #include <netinet/if_ether.h> #include <netinet/tcp.h> #include <netinet/tcp_seq.h> +#include <sys/pool.h> #ifdef INET #include <netinet/in_systm.h> @@ -124,9 +126,9 @@ pfsync_clone_create(struct if_clone *ifc return (EINVAL); pfsync_sync_ok = 1; - if ((pfsyncif = malloc(sizeof(*pfsyncif), M_DEVBUF, M_NOWAIT)) == NULL) + if ((pfsyncif = malloc(sizeof(*pfsyncif), M_DEVBUF, + M_NOWAIT|M_ZERO)) == NULL) return (ENOMEM); - bzero(pfsyncif, sizeof(*pfsyncif)); pfsyncif->sc_mbuf = NULL; pfsyncif->sc_mbuf_net = NULL; pfsyncif->sc_mbuf_tdb = NULL; @@ -140,6 +142,10 @@ pfsync_clone_create(struct if_clone *ifc pfsyncif->sc_ureq_sent = 0; pfsyncif->sc_bulk_send_next = NULL; pfsyncif->sc_bulk_terminator = NULL; + pfsyncif->sc_imo.imo_membership = (struct in_multi **)malloc( + (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, + M_WAITOK|M_ZERO); + pfsyncif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; ifp = &pfsyncif->sc_if; snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit); ifp->if_softc = pfsyncif; @@ -171,10 +177,21 @@ pfsync_clone_create(struct if_clone *ifc int pfsync_clone_destroy(struct ifnet *ifp) { + struct pfsync_softc *sc = ifp->if_softc; + + timeout_del(&sc->sc_tmo); + timeout_del(&sc->sc_tdb_tmo); + timeout_del(&sc->sc_bulk_tmo); + timeout_del(&sc->sc_bulkfail_tmo); +#if NCARP > 0 + if (!pfsync_sync_ok) + carp_group_demote_adj(&sc->sc_if, -1); +#endif #if NBPFILTER > 0 bpfdetach(ifp); #endif if_detach(ifp); + free(pfsyncif->sc_imo.imo_membership, M_IPMOPTS); free(pfsyncif, M_DEVBUF); pfsyncif = NULL; return (0); @@ -461,9 +478,9 @@ pfsync_input(struct mbuf *m, ...) 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: " + printf("pfsync_input: PFSYNC_ACT_INS: " "invalid value\n"); - pfsyncstats.pfsyncs_badstate++; + pfsyncstats.pfsyncs_badval++; continue; } @@ -495,9 +512,9 @@ pfsync_input(struct mbuf *m, ...) 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: " + printf("pfsync_input: PFSYNC_ACT_UPD: " "invalid value\n"); - pfsyncstats.pfsyncs_badstate++; + pfsyncstats.pfsyncs_badval++; continue; } @@ -559,7 +576,7 @@ pfsync_input(struct mbuf *m, ...) : "partial"), sfail, betoh64(st->id), ntohl(st->creatorid)); - pfsyncstats.pfsyncs_badstate++; + pfsyncstats.pfsyncs_stale++; if (!(sp->sync_flags & PFSTATE_STALE)) { /* we have a better state, send it */ @@ -626,10 +643,10 @@ pfsync_input(struct mbuf *m, ...) up->src.state > PF_TCPS_PROXY_DST || up->dst.state > PF_TCPS_PROXY_DST) { if (pf_status.debug >= PF_DEBUG_MISC) - printf("pfsync_insert: " + printf("pfsync_input: " "PFSYNC_ACT_UPD_C: " "invalid value\n"); - pfsyncstats.pfsyncs_badstate++; + pfsyncstats.pfsyncs_badval++; continue; } @@ -685,7 +702,7 @@ pfsync_input(struct mbuf *m, ...) "creatorid: %08x\n", sfail, betoh64(st->id), ntohl(st->creatorid)); - pfsyncstats.pfsyncs_badstate++; + pfsyncstats.pfsyncs_stale++; /* we have a better state, send it out */ if ((!stale || update_requested) && @@ -1750,3 +1767,22 @@ pfsync_update_tdb(struct tdb *tdb, int o return (ret); } #endif + +int +pfsync_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) +{ + /* 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, + &pfsyncstats, sizeof(pfsyncstats))); + default: + return (ENOPROTOOPT); + } +} Modified: vendor-sys/pf/dist/net/if_pfsync.h ============================================================================== --- vendor-sys/pf/dist/net/if_pfsync.h Wed Dec 10 21:22:15 2008 (r185885) +++ vendor-sys/pf/dist/net/if_pfsync.h Wed Dec 10 21:22:57 2008 (r185886) @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.h,v 1.31 2007/05/31 04:11:42 mcbride Exp $ */ +/* $OpenBSD: if_pfsync.h,v 1.32 2007/12/14 18:33:37 deraadt Exp $ */ /* * Copyright (c) 2001 Michael Shalayeff @@ -86,6 +86,17 @@ struct pfsync_state_bus { u_int8_t pad[7]; } __packed; +/* + * Names for PFSYNC sysctl objects + */ +#define PFSYNCCTL_STATS 1 /* PFSYNC stats */ +#define PFSYNCCTL_MAXID 2 + +#define PFSYNCCTL_NAMES { \ + { 0, 0 }, \ + { "stats", CTLTYPE_STRUCT }, \ +} + #ifdef _KERNEL union sc_statep { @@ -255,6 +266,8 @@ struct pfsyncreq { void pfsync_input(struct mbuf *, ...); int pfsync_clear_states(u_int32_t, char *); int pfsync_pack_state(u_int8_t, struct pf_state *, int); +int pfsync_sysctl(int *, u_int, void *, size_t *, void *, size_t); + #define pfsync_insert_state(st) do { \ if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \ (st->state_key->proto == IPPROTO_PFSYNC)) \ Modified: vendor-sys/pf/dist/net/pf.c ============================================================================== --- vendor-sys/pf/dist/net/pf.c Wed Dec 10 21:22:15 2008 (r185885) +++ vendor-sys/pf/dist/net/pf.c Wed Dec 10 21:22:57 2008 (r185886) @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.552 2007/08/21 15:57:27 dhartmei Exp $ */ +/* $OpenBSD: pf.c,v 1.567 2008/02/20 23:40:13 henning Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -51,6 +51,8 @@ #include <sys/proc.h> #include <sys/rwlock.h> +#include <crypto/md5.h> + #include <net/if.h> #include <net/if_types.h> #include <net/bpf.h> @@ -110,6 +112,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; @@ -160,6 +167,7 @@ struct pf_rule *pf_get_translation(stru void pf_attach_state(struct pf_state_key *, struct pf_state *, int); void pf_detach_state(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 **, @@ -214,7 +222,7 @@ int pf_check_proto_cksum(struct mbuf int pf_addr_wrap_neq(struct pf_addr_wrap *, struct pf_addr_wrap *); struct pf_state *pf_find_state(struct pfi_kif *, - struct pf_state_key_cmp *, u_int8_t); + struct pf_state_key_cmp *, u_int); int pf_src_connlimit(struct pf_state **); void pf_stateins_err(const char *, struct pf_state *, struct pfi_kif *); @@ -233,10 +241,7 @@ struct pf_pool_limit pf_pool_limits[PF_L #define STATE_LOOKUP() \ do { \ - if (direction == PF_IN) \ - *state = pf_find_state(kif, &key, PF_EXT_GWY); \ - else \ - *state = pf_find_state(kif, &key, PF_LAN_EXT); \ + *state = pf_find_state(kif, &key, direction); \ if (*state == NULL || (*state)->timeout == PFTM_PURGE) \ return (PF_DROP); \ if (direction == PF_OUT && \ @@ -526,19 +531,19 @@ pf_find_state_byid(struct pf_state_cmp * } struct pf_state * -pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int8_t tree) +pf_find_state(struct pfi_kif *kif, struct pf_state_key_cmp *key, u_int dir) { struct pf_state_key *sk; struct pf_state *s; pf_status.fcounters[FCNT_STATE_SEARCH]++; - switch (tree) { - case PF_LAN_EXT: + switch (dir) { + case PF_OUT: sk = RB_FIND(pf_state_tree_lan_ext, &pf_statetbl_lan_ext, (struct pf_state_key *)key); break; - case PF_EXT_GWY: + case PF_IN: sk = RB_FIND(pf_state_tree_ext_gwy, &pf_statetbl_ext_gwy, (struct pf_state_key *)key); break; @@ -556,19 +561,19 @@ pf_find_state(struct pfi_kif *kif, struc } struct pf_state * -pf_find_state_all(struct pf_state_key_cmp *key, u_int8_t tree, int *more) +pf_find_state_all(struct pf_state_key_cmp *key, u_int dir, int *more) { struct pf_state_key *sk; struct pf_state *s, *ret = NULL; pf_status.fcounters[FCNT_STATE_SEARCH]++; - switch (tree) { - case PF_LAN_EXT: + switch (dir) { + case PF_OUT: sk = RB_FIND(pf_state_tree_lan_ext, &pf_statetbl_lan_ext, (struct pf_state_key *)key); break; - case PF_EXT_GWY: + case PF_IN: sk = RB_FIND(pf_state_tree_ext_gwy, &pf_statetbl_ext_gwy, (struct pf_state_key *)key); break; @@ -819,6 +824,8 @@ pf_insert_state(struct pfi_kif *kif, str TAILQ_FOREACH(sp, &cur->states, next) if (sp->kif == kif) { /* collision! */ pf_stateins_err("tree_lan_ext", s, kif); + pf_detach_state(s, + PF_DT_SKIP_LANEXT|PF_DT_SKIP_EXTGWY); return (-1); } pf_detach_state(s, PF_DT_SKIP_LANEXT|PF_DT_SKIP_EXTGWY); @@ -961,10 +968,8 @@ pf_src_tree_remove_state(struct pf_state u_int32_t timeout; if (s->src_node != NULL) { - if (s->state_key->proto == IPPROTO_TCP) { - if (s->src.tcp_est) - --s->src_node->conn; - } + 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) @@ -1295,6 +1300,7 @@ pf_addr_wrap_neq(struct pf_addr_wrap *aw 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)) @@ -1598,7 +1604,7 @@ pf_send_tcp(const struct pf_rule *r, sa_ m->m_pkthdr.pf.tag = rtag; if (r != NULL && r->rtableid >= 0) - m->m_pkthdr.pf.rtableid = m->m_pkthdr.pf.rtableid; + m->m_pkthdr.pf.rtableid = r->rtableid; #ifdef ALTQ if (r != NULL && r->qid) { @@ -1790,6 +1796,44 @@ pf_match_addr(u_int8_t n, struct pf_addr } } +/* + * 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) { @@ -2267,15 +2311,15 @@ pf_get_sport(sa_family_t af, u_int8_t pr 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) + if (pf_find_state_all(&key, PF_IN, 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) + if (pf_find_state_all(&key, PF_IN, NULL) == NULL) return (0); } else if (low == high) { key.gwy.port = htons(low); - if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) { + if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { *nport = htons(low); return (0); } @@ -2292,7 +2336,7 @@ pf_get_sport(sa_family_t af, u_int8_t pr /* low <= cut <= high */ for (tmp = cut; tmp <= high; ++(tmp)) { key.gwy.port = htons(tmp); - if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == + if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { *nport = htons(tmp); return (0); @@ -2300,7 +2344,7 @@ pf_get_sport(sa_family_t af, u_int8_t pr } for (tmp = cut - 1; tmp >= low; --(tmp)) { key.gwy.port = htons(tmp); - if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == + if (pf_find_state_all(&key, PF_IN, NULL) == NULL) { *nport = htons(tmp); return (0); @@ -2836,6 +2880,34 @@ pf_alloc_state_key(struct pf_state *s) return (sk); } +u_int32_t +pf_tcp_iss(struct pf_pdesc *pd) +{ + MD5_CTX ctx; + u_int32_t digest[4]; + + if (pf_tcp_secret_init == 0) { + arc4random_bytes(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; + + 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); + pf_tcp_iss_off += 4096; + return (digest[0] + tcp_iss + pf_tcp_iss_off); +} + int pf_test_rule(struct pf_rule **rm, struct pf_state **sm, int direction, struct pfi_kif *kif, struct mbuf *m, int off, void *h, @@ -3077,7 +3149,8 @@ pf_test_rule(struct pf_rule **rm, struct !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 && r->prob <= + (arc4random() % (UINT_MAX - 1) + 1)) r = TAILQ_NEXT(r, entries); else if (r->match_tag && !pf_match_tag(m, r, &tag)) r = TAILQ_NEXT(r, entries); @@ -3203,10 +3276,22 @@ pf_test_rule(struct pf_rule **rm, struct (r->rule_flag & PFRULE_RETURN)) && !(th->th_flags & TH_RST)) { u_int32_t ack = ntohl(th->th_seq) + pd->p_len; - struct ip *h = mtod(m, struct ip *); + int len = 0; + struct ip *h4; + struct ip6_hdr *h6; + + switch (af) { + case AF_INET: + h4 = mtod(m, struct ip *); + len = ntohs(h4->ip_len) - off; + break; + case AF_INET6: + h6 = mtod(m, struct ip6_hdr *); + len = ntohs(h6->ip6_plen) - (off - sizeof(*h6)); + break; + } - if (pf_check_proto_cksum(m, off, - ntohs(h->ip_len) - off, IPPROTO_TCP, AF_INET)) + if (pf_check_proto_cksum(m, off, len, IPPROTO_TCP, af)) REASON_SET(&reason, PFRES_PROTCKSUM); else { if (th->th_flags & TH_SYN) @@ -3218,10 +3303,12 @@ pf_test_rule(struct pf_rule **rm, struct 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) + } 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); } @@ -3237,7 +3324,6 @@ pf_test_rule(struct pf_rule **rm, struct if (!state_icmp && (r->keep_state || nr != NULL || (pd->flags & PFDESC_TCP_NORM))) { /* create new state */ - u_int16_t len; struct pf_state *s = NULL; struct pf_state_key *sk = NULL; struct pf_src_node *sn = NULL; @@ -3296,15 +3382,14 @@ cleanup: s->log |= nr->log & PF_LOG_ALL; switch (pd->proto) { case IPPROTO_TCP: - len = pd->tot_len - off - (th->th_off << 2); s->src.seqlo = ntohl(th->th_seq); - s->src.seqhi = s->src.seqlo + len + 1; + 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 */ - while ((s->src.seqdiff = - tcp_rndiss_next() - s->src.seqlo) == 0) - ; + 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; @@ -3525,11 +3610,20 @@ pf_test_fragment(struct pf_rule **rm, in r = r->skip[PF_SKIP_DST_ADDR].ptr; else if (r->tos && !(r->tos == pd->tos)) r = TAILQ_NEXT(r, entries); - else if (r->src.port_op || r->dst.port_op || - r->flagset || r->type || r->code || - r->os_fingerprint != PF_OSFP_ANY) + else if (r->os_fingerprint != PF_OSFP_ANY) + r = TAILQ_NEXT(r, entries); + else if (pd->proto == IPPROTO_UDP && + (r->src.port_op || r->dst.port_op)) r = TAILQ_NEXT(r, entries); - else if (r->prob && r->prob <= arc4random()) + else if (pd->proto == IPPROTO_TCP && + (r->src.port_op || r->dst.port_op || r->flagset)) + r = TAILQ_NEXT(r, entries); + else if ((pd->proto == IPPROTO_ICMP || + pd->proto == IPPROTO_ICMPV6) && + (r->type || r->code)) + r = TAILQ_NEXT(r, entries); + 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, &tag)) r = TAILQ_NEXT(r, entries); @@ -3698,6 +3792,22 @@ pf_test_state_tcp(struct pf_state **stat } } + if (((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) && + dst->state >= TCPS_FIN_WAIT_2 && + src->state >= TCPS_FIN_WAIT_2) { + if (pf_status.debug >= PF_DEBUG_MISC) { + printf("pf: state reuse "); + pf_print_state(*state); + pf_print_flags(th->th_flags); + printf("\n"); + } + /* XXX make sure it's the same direction ?? */ + (*state)->src.state = (*state)->dst.state = TCPS_CLOSED; + pf_unlink_state(*state); + *state = NULL; + return (PF_DROP); + } + if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) { sws = src->wscale & PF_WSCALE_MASK; dws = dst->wscale & PF_WSCALE_MASK; @@ -3724,7 +3834,8 @@ pf_test_state_tcp(struct pf_state **stat /* Deferred generation of sequence number modulator */ if (dst->seqdiff && !src->seqdiff) { - while ((src->seqdiff = tcp_rndiss_next() - seq) == 0) + /* use random iss for the TCP server */ + while ((src->seqdiff = arc4random() - seq) == 0) ; ack = ntohl(th->th_ack) - dst->seqdiff; pf_change_a(&th->th_seq, &th->th_sum, htonl(seq + @@ -3842,7 +3953,8 @@ pf_test_state_tcp(struct pf_state **stat (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) { @@ -3937,9 +4049,12 @@ pf_test_state_tcp(struct pf_state **stat 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, - ackskew, (*state)->packets[0], - (*state)->packets[1]); + "pkts=%llu:%llu dir=%s,%s\n", seq, orig_seq, ack, + pd->p_len, ackskew, (*state)->packets[0], + (*state)->packets[1], + direction == PF_IN ? "in" : "out", + direction == (*state)->state_key->direction ? + "fwd" : "rev"); } if (dst->scrub || src->scrub) { Modified: vendor-sys/pf/dist/net/pf_if.c ============================================================================== --- vendor-sys/pf/dist/net/pf_if.c Wed Dec 10 21:22:15 2008 (r185885) +++ vendor-sys/pf/dist/net/pf_if.c Wed Dec 10 21:22:57 2008 (r185886) @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_if.c,v 1.47 2007/07/13 09:17:48 markus Exp $ */ +/* $OpenBSD: pf_if.c,v 1.51 2007/11/07 17:28:40 mpf Exp $ */ /* * Copyright 2005 Henning Brauer <henning@openbsd.org> @@ -41,6 +41,7 @@ #include <sys/kernel.h> #include <sys/device.h> #include <sys/time.h> +#include <sys/pool.h> #include <net/if.h> #include <net/if_types.h> @@ -110,10 +111,9 @@ pfi_kif_get(const char *kif_name) return (kif); /* create new one */ - if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT)) == NULL) + if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT|M_ZERO)) == NULL) return (NULL); - bzero(kif, sizeof(*kif)); strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name)); kif->pfik_tzero = time_second; TAILQ_INIT(&kif->pfik_dynaddrs); @@ -603,49 +603,57 @@ pfi_if_compare(struct pfi_kif *p, struct } 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 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(); p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key); 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 Modified: vendor-sys/pf/dist/net/pf_ioctl.c ============================================================================== --- vendor-sys/pf/dist/net/pf_ioctl.c Wed Dec 10 21:22:15 2008 (r185885) +++ vendor-sys/pf/dist/net/pf_ioctl.c Wed Dec 10 21:22:57 2008 (r185886) @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_ioctl.c,v 1.182 2007/06/24 11:17:13 mcbride Exp $ */ +/* $OpenBSD: pf_ioctl.c,v 1.193 2007/12/02 12:08:04 pascoe Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -160,7 +160,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 (ptoa(physmem) <= 100*1024*1024) pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT_SMALL; @@ -379,11 +379,9 @@ tagname2tag(struct pf_tags *head, char * 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++; @@ -912,7 +910,6 @@ pf_state_import(struct pfsync_state *sp, /* copy to state */ memcpy(&s->id, &sp->id, sizeof(sp->id)); s->creatorid = sp->creatorid; - strlcpy(sp->ifname, s->kif->pfik_name, sizeof(sp->ifname)); pf_state_peer_from_pfsync(&sp->src, &s->src); pf_state_peer_from_pfsync(&sp->dst, &s->dst); @@ -921,6 +918,9 @@ pf_state_import(struct pfsync_state *sp, s->anchor.ptr = NULL; s->rt_kif = NULL; s->creation = time_second; + s->expire = time_second; + if (sp->expire > 0) + s->expire -= pf_default_rule.timeout[sp->timeout] - sp->expire; s->pfsync_time = 0; s->packets[0] = s->packets[1] = 0; s->bytes[0] = s->bytes[1] = 0; @@ -1633,7 +1633,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a case DIOCADDSTATE: { struct pfioc_state *ps = (struct pfioc_state *)addr; - struct pfsync_state *sp = (struct pfsync_state *)ps->state; + struct pfsync_state *sp = &ps->state; struct pf_state *s; struct pf_state_key *sk; struct pfi_kif *kif; @@ -1650,6 +1650,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a } bzero(s, sizeof(struct pf_state)); if ((sk = pf_alloc_state_key(s)) == NULL) { + pool_put(&pf_state_pl, s); error = ENOMEM; break; } @@ -1664,30 +1665,28 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a if (pf_insert_state(kif, s)) { pfi_kif_unref(kif, PFI_KIF_REF_NONE); pool_put(&pf_state_pl, s); - pool_put(&pf_state_key_pl, sk); - error = ENOMEM; + error = EEXIST; + break; } + pf_default_rule.states++; break; } case DIOCGETSTATE: { struct pfioc_state *ps = (struct pfioc_state *)addr; struct pf_state *s; - u_int32_t nr; + struct pf_state_cmp id_key; - nr = 0; - RB_FOREACH(s, pf_state_tree_id, &tree_id) { - if (nr >= ps->nr) - break; - nr++; - } + 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 = EBUSY; + error = ENOENT; break; } - pf_state_export((struct pfsync_state *)&ps->state, - s->state_key, s); + pf_state_export(&ps->state, s->state_key, s); break; } @@ -1735,7 +1734,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a case DIOCGETSTATUS: { struct pf_status *s = (struct pf_status *)addr; bcopy(&pf_status, s, sizeof(struct pf_status)); - pfi_fill_oldstatus(s); + pfi_update_status(s->ifname, s); break; } @@ -1746,10 +1745,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a bzero(pf_status.ifname, IFNAMSIZ); break; } - if (ifunit(pi->ifname) == NULL) { - error = EINVAL; - break; - } strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ); break; } @@ -1760,7 +1755,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a 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); break; } @@ -1793,13 +1788,13 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a 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); + state = pf_find_state_all(&key, PF_IN, &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); + state = pf_find_state_all(&key, PF_OUT, &m); } if (m > 1) error = E2BIG; /* more than one state */ @@ -1968,6 +1963,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a pool_put(&pf_altq_pl, altq); break; } + altq->altq_disc = NULL; TAILQ_FOREACH(a, pf_altqs_inactive, entries) { if (strncmp(a->ifname, altq->ifname, IFNAMSIZ) == 0 && a->qname[0] == 0) { @@ -2547,10 +2543,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a error = ENODEV; goto fail; } - 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); for (i = 0; i < io->size; i++) { if (copyin(io->array+i, ioe, sizeof(*ioe))) { free(table, M_TEMP); @@ -2616,10 +2610,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a error = ENODEV; goto fail; } - 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); for (i = 0; i < io->size; i++) { if (copyin(io->array+i, ioe, sizeof(*ioe))) { free(table, M_TEMP); @@ -2680,10 +2672,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a error = ENODEV; goto fail; } - 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); /* first makes sure everything will succeed */ for (i = 0; i < io->size; i++) { if (copyin(io->array+i, ioe, sizeof(*ioe))) { Modified: vendor-sys/pf/dist/net/pf_norm.c ============================================================================== --- vendor-sys/pf/dist/net/pf_norm.c Wed Dec 10 21:22:15 2008 (r185885) +++ vendor-sys/pf/dist/net/pf_norm.c Wed Dec 10 21:22:57 2008 (r185886) @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_norm.c,v 1.109 2007/05/28 17:16:39 henning Exp $ */ +/* $OpenBSD: pf_norm.c,v 1.111 2007/12/30 10:32:24 mglocker Exp $ */ /* * Copyright 2001 Niels Provos <provos@citi.umich.edu> @@ -115,7 +115,7 @@ struct mbuf *pf_reassemble(struct mbuf 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); #define DPFPRINTF(x) do { \ if (pf_status.debug >= PF_DEBUG_MISC) { \ @@ -1316,7 +1316,7 @@ pf_normalize_tcp(int dir, struct pfi_kif } /* 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 */ @@ -1819,17 +1819,21 @@ pf_normalize_tcp_stateful(struct mbuf *m 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; + u_char opts[MAX_TCPOPTLEN]; + u_char *optp = opts; thoff = th->th_off << 2; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812102122.mBALMvpq043303>