-/* $OpenBSD: pf.c,v 1.1068 2018/06/18 11:00:31 procter Exp $ */
+/* $OpenBSD: pf.c,v 1.1069 2018/07/10 09:28:27 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
struct pool pf_src_tree_pl, pf_rule_pl, pf_queue_pl;
struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl;
-struct pool pf_rule_item_pl, pf_sn_item_pl;
+struct pool pf_rule_item_pl, pf_sn_item_pl, pf_pktdelay_pl;
void pf_add_threshold(struct pf_threshold *);
int pf_check_threshold(struct pf_threshold *);
struct inpcb *);
void pf_state_key_unlink_inpcb(struct pf_state_key *);
void pf_inpcb_unlink_state_key(struct inpcb *);
+void pf_pktenqueue_delayed(void *);
#if NPFLOG > 0
void pf_log_matches(struct pf_pdesc *, struct pf_rule *,
{ &pf_src_tree_pl, PFSNODE_HIWAT, PFSNODE_HIWAT },
{ &pf_frent_pl, PFFRAG_FRENT_HIWAT, PFFRAG_FRENT_HIWAT },
{ &pfr_ktable_pl, PFR_KTABLE_HIWAT, PFR_KTABLE_HIWAT },
- { &pfr_kentry_pl, PFR_KENTRY_HIWAT, PFR_KENTRY_HIWAT }
+ { &pfr_kentry_pl, PFR_KENTRY_HIWAT, PFR_KENTRY_HIWAT },
+ { &pf_pktdelay_pl, PF_PKTDELAY_MAXPKTS, PF_PKTDELAY_MAXPKTS }
};
#define STATE_LOOKUP(i, k, d, s, m) \
a->set_prio[0] = r->set_prio[0];
a->set_prio[1] = r->set_prio[1];
}
+ if (r->rule_flag & PFRULE_SETDELAY)
+ a->delay = r->delay;
}
#define PF_TEST_ATTRIB(t, a) \
#endif /* NPFSYNC > 0 */
s->set_prio[0] = act->set_prio[0];
s->set_prio[1] = act->set_prio[1];
+ s->delay = act->delay;
SLIST_INIT(&s->src_nodes);
switch (pd->proto) {
if (s->state_flags & PFSTATE_SETPRIO)
pd.m->m_pkthdr.pf.prio = s->set_prio[0];
}
+ pd.m->m_pkthdr.pf.delay = s->delay;
} else {
pf_scrub(pd.m, r->scrub_flags, pd.af, r->min_ttl,
r->set_tos);
if (r->scrub_flags & PFSTATE_SETPRIO)
pd.m->m_pkthdr.pf.prio = r->set_prio[0];
}
+ pd.m->m_pkthdr.pf.delay = r->delay;
}
}
pf_state_key_unref(sk);
}
}
+
+int
+pf_delay_pkt(struct mbuf *m, u_int ifidx)
+{
+ struct pf_pktdelay *pdy;
+
+ if ((pdy = pool_get(&pf_pktdelay_pl, PR_NOWAIT)) == NULL) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ pdy->ifidx = ifidx;
+ pdy->m = m;
+ timeout_set(pdy->to, pf_pktenqueue_delayed, pdy);
+ timeout_add_msec(pdy->to, m->m_pkthdr.pf.delay);
+ m->m_pkthdr.pf.delay = 0;
+ return (0);
+}
+
+void
+pf_pktenqueue_delayed(void *arg)
+{
+ struct pf_pktdelay *pdy = arg;
+ struct ifnet *ifp;
+
+ ifp = if_get(pdy->ifidx);
+ if (ifp != NULL) {
+ if_enqueue(ifp, pdy->m);
+ if_put(ifp);
+ } else
+ m_freem(pdy->m);
+
+ pool_put(&pf_pktdelay_pl, pdy);
+}
-/* $OpenBSD: pf_ioctl.c,v 1.334 2018/04/24 23:05:09 bluhm Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.335 2018/07/10 09:28:27 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
IPL_SOFTNET, 0, "pfqueue", NULL);
pool_init(&pf_tag_pl, sizeof(struct pf_tagname), 0,
IPL_SOFTNET, 0, "pftag", NULL);
+ pool_init(&pf_pktdelay_pl, sizeof(struct pf_pktdelay), 0,
+ IPL_SOFTNET, 0, "pfpktdelay", NULL);
+
hfsc_initialize();
pfr_initialize();
pfi_initialize();
-/* $OpenBSD: pfvar.h,v 1.478 2018/06/18 11:00:31 procter Exp $ */
+/* $OpenBSD: pfvar.h,v 1.479 2018/07/10 09:28:27 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
enum { PF_NOPFROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO };
enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS,
- PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX };
+ PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_PKTDELAY_PKTS,
+ PF_LIMIT_MAX };
#define PF_POOL_IDMASK 0x0f
enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM,
PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN, PF_POOL_LEASTSTATES };
u_int16_t pqid;
u_int16_t max_mss;
u_int16_t flags;
+ u_int16_t delay;
u_int8_t log;
u_int8_t set_tos;
u_int8_t min_ttl;
u_int8_t set_prio[2];
- u_int8_t pad[3];
+ u_int8_t pad[1];
};
union pf_rule_ptr {
u_int16_t tag;
u_int16_t match_tag;
u_int16_t scrub_flags;
+ u_int16_t delay;
struct pf_rule_uid uid;
struct pf_rule_gid gid;
#define PFRULE_RETURNICMP 0x0004
#define PFRULE_RETURN 0x0008
#define PFRULE_NOSYNC 0x0010
-#define PFRULE_SRCTRACK 0x0020 /* track source states */
-#define PFRULE_RULESRCTRACK 0x0040 /* per rule */
+#define PFRULE_SRCTRACK 0x0020 /* track source states */
+#define PFRULE_RULESRCTRACK 0x0040 /* per rule */
+#define PFRULE_SETDELAY 0x0080
/* rule flags again */
#define PFRULE_IFBOUND 0x00010000 /* if-bound */
#define PFSTATE_HIWAT 10000 /* default state table size */
#define PFSTATE_ADAPT_START 6000 /* default adaptive timeout start */
#define PFSTATE_ADAPT_END 12000 /* default adaptive timeout end */
-
+#define PF_PKTDELAY_MAXPKTS 10000 /* max # of pkts held in delay queue */
struct pf_rule_item {
SLIST_ENTRY(pf_rule_item) entry;
int32_t creation;
int32_t expire;
int32_t pfsync_time;
+ int rtableid[2]; /* rtables stack and wire */
u_int16_t qid;
u_int16_t pqid;
u_int16_t tag;
u_int8_t timeout;
u_int8_t sync_state; /* PFSYNC_S_x */
u_int8_t sync_updates;
- int rtableid[2]; /* rtables stack and wire */
u_int8_t min_ttl;
u_int8_t set_tos;
u_int8_t set_prio[2];
u_int16_t max_mss;
u_int16_t if_index_in;
u_int16_t if_index_out;
- u_int8_t pad2[2];
+ u_int16_t delay;
};
/*
PF_DIVERT_PACKET
};
+struct pf_pktdelay {
+ struct timeout *to;
+ struct mbuf *m;
+ u_int ifidx;
+};
+
/* Fragment entries reference mbuf clusters, so base the default on that. */
#define PFFRAG_FRENT_HIWAT (NMBCLUSTERS / 16) /* Number of entries */
#define PFFRAG_FRAG_HIWAT (NMBCLUSTERS / 32) /* Number of packets */
extern u_int32_t ticket_pabuf;
extern struct pool pf_src_tree_pl, pf_sn_item_pl, pf_rule_pl;
extern struct pool pf_state_pl, pf_state_key_pl, pf_state_item_pl,
- pf_rule_item_pl, pf_queue_pl;
+ pf_rule_item_pl, pf_queue_pl,
+ pf_pktdelay_pl;
extern struct pool pf_state_scrub_pl;
extern struct ifnet *sync_ifp;
extern struct pf_rule pf_default_rule;
void pf_route(struct pf_pdesc *, struct pf_rule *, struct pf_state *);
void pf_route6(struct pf_pdesc *, struct pf_rule *, struct pf_state *);
void pf_init_threshold(struct pf_threshold *, u_int32_t, u_int32_t);
+int pf_delay_pkt(struct mbuf *, u_int);
void pfr_initialize(void);
int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
-/* $OpenBSD: mbuf.h,v 1.235 2018/02/11 00:24:13 dlg Exp $ */
+/* $OpenBSD: mbuf.h,v 1.236 2018/07/10 09:28:27 henning Exp $ */
/* $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $ */
/*
struct inpcb *inp; /* connected pcb for outgoing packet */
u_int32_t qid; /* queue id */
u_int16_t tag; /* tag id */
+ u_int16_t delay; /* delay packet by X ms */
u_int8_t flags;
u_int8_t routed;
u_int8_t prio;
- u_int8_t pad[3];
+ u_int8_t pad[1];
};
/* pkthdr_pf.flags */