Skip to content

Commit a0073fe

Browse files
committed
xfrm: Add a state resolution packet queue
As the default, we blackhole packets until the key manager resolves the states. This patch implements a packet queue where IPsec packets are queued until the states are resolved. We generate a dummy xfrm bundle, the output routine of the returned route enqueues the packet to a per policy queue and arms a timer that checks for state resolution when dst_output() is called. Once the states are resolved, the packets are sent out of the queue. If the states are not resolved after some time, the queue is flushed. This patch keeps the defaut behaviour to blackhole packets as long as we have no states. To enable the packet queue the sysctl xfrm_larval_drop must be switched off. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
1 parent fa8599d commit a0073fe

File tree

3 files changed

+233
-4
lines changed

3 files changed

+233
-4
lines changed

include/net/dst.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct dst_entry {
6161
#define DST_NOPEER 0x0040
6262
#define DST_FAKE_RTABLE 0x0080
6363
#define DST_XFRM_TUNNEL 0x0100
64+
#define DST_XFRM_QUEUE 0x0200
6465

6566
unsigned short pending_confirm;
6667

include/net/xfrm.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,12 @@ struct xfrm_policy_walk {
501501
u32 seq;
502502
};
503503

504+
struct xfrm_policy_queue {
505+
struct sk_buff_head hold_queue;
506+
struct timer_list hold_timer;
507+
unsigned long timeout;
508+
};
509+
504510
struct xfrm_policy {
505511
#ifdef CONFIG_NET_NS
506512
struct net *xp_net;
@@ -522,6 +528,7 @@ struct xfrm_policy {
522528
struct xfrm_lifetime_cfg lft;
523529
struct xfrm_lifetime_cur curlft;
524530
struct xfrm_policy_walk_entry walk;
531+
struct xfrm_policy_queue polq;
525532
u8 type;
526533
u8 action;
527534
u8 flags;

net/xfrm/xfrm_policy.c

Lines changed: 225 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
#include "xfrm_hash.h"
3737

38+
#define XFRM_QUEUE_TMO_MIN ((unsigned)(HZ/10))
39+
#define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ))
40+
#define XFRM_MAX_QUEUE_LEN 100
41+
3842
DEFINE_MUTEX(xfrm_cfg_mutex);
3943
EXPORT_SYMBOL(xfrm_cfg_mutex);
4044

@@ -51,7 +55,7 @@ static struct kmem_cache *xfrm_dst_cache __read_mostly;
5155
static void xfrm_init_pmtu(struct dst_entry *dst);
5256
static int stale_bundle(struct dst_entry *dst);
5357
static int xfrm_bundle_ok(struct xfrm_dst *xdst);
54-
58+
static void xfrm_policy_queue_process(unsigned long arg);
5559

5660
static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
5761
int dir);
@@ -287,8 +291,11 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
287291
INIT_HLIST_NODE(&policy->byidx);
288292
rwlock_init(&policy->lock);
289293
atomic_set(&policy->refcnt, 1);
294+
skb_queue_head_init(&policy->polq.hold_queue);
290295
setup_timer(&policy->timer, xfrm_policy_timer,
291296
(unsigned long)policy);
297+
setup_timer(&policy->polq.hold_timer, xfrm_policy_queue_process,
298+
(unsigned long)policy);
292299
policy->flo.ops = &xfrm_policy_fc_ops;
293300
}
294301
return policy;
@@ -309,6 +316,16 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
309316
}
310317
EXPORT_SYMBOL(xfrm_policy_destroy);
311318

319+
static void xfrm_queue_purge(struct sk_buff_head *list)
320+
{
321+
struct sk_buff *skb;
322+
323+
while ((skb = skb_dequeue(list)) != NULL) {
324+
dev_put(skb->dev);
325+
kfree_skb(skb);
326+
}
327+
}
328+
312329
/* Rule must be locked. Release descentant resources, announce
313330
* entry dead. The rule must be unlinked from lists to the moment.
314331
*/
@@ -319,6 +336,9 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
319336

320337
atomic_inc(&policy->genid);
321338

339+
del_timer(&policy->polq.hold_timer);
340+
xfrm_queue_purge(&policy->polq.hold_queue);
341+
322342
if (del_timer(&policy->timer))
323343
xfrm_pol_put(policy);
324344

@@ -562,6 +582,31 @@ static inline int selector_cmp(struct xfrm_selector *s1, struct xfrm_selector *s
562582
return 0;
563583
}
564584

585+
static void xfrm_policy_requeue(struct xfrm_policy *old,
586+
struct xfrm_policy *new)
587+
{
588+
struct xfrm_policy_queue *pq = &old->polq;
589+
struct sk_buff_head list;
590+
591+
__skb_queue_head_init(&list);
592+
593+
spin_lock_bh(&pq->hold_queue.lock);
594+
skb_queue_splice_init(&pq->hold_queue, &list);
595+
del_timer(&pq->hold_timer);
596+
spin_unlock_bh(&pq->hold_queue.lock);
597+
598+
if (skb_queue_empty(&list))
599+
return;
600+
601+
pq = &new->polq;
602+
603+
spin_lock_bh(&pq->hold_queue.lock);
604+
skb_queue_splice(&list, &pq->hold_queue);
605+
pq->timeout = XFRM_QUEUE_TMO_MIN;
606+
mod_timer(&pq->hold_timer, jiffies);
607+
spin_unlock_bh(&pq->hold_queue.lock);
608+
}
609+
565610
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
566611
{
567612
struct net *net = xp_net(policy);
@@ -603,8 +648,10 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
603648
net->xfrm.policy_count[dir]++;
604649
atomic_inc(&flow_cache_genid);
605650
rt_genid_bump(net);
606-
if (delpol)
651+
if (delpol) {
652+
xfrm_policy_requeue(delpol, policy);
607653
__xfrm_policy_unlink(delpol, dir);
654+
}
608655
policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir);
609656
hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index));
610657
policy->curlft.add_time = get_seconds();
@@ -1115,11 +1162,15 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
11151162
pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir);
11161163
__xfrm_policy_link(pol, XFRM_POLICY_MAX+dir);
11171164
}
1118-
if (old_pol)
1165+
if (old_pol) {
1166+
if (pol)
1167+
xfrm_policy_requeue(old_pol, pol);
1168+
11191169
/* Unlinking succeeds always. This is the only function
11201170
* allowed to delete or replace socket policy.
11211171
*/
11221172
__xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir);
1173+
}
11231174
write_unlock_bh(&xfrm_policy_lock);
11241175

11251176
if (old_pol) {
@@ -1310,6 +1361,8 @@ static struct flow_cache_object *xfrm_bundle_flo_get(struct flow_cache_object *f
13101361
* It means we need to try again resolving. */
13111362
if (xdst->num_xfrms > 0)
13121363
return NULL;
1364+
} else if (dst->flags & DST_XFRM_QUEUE) {
1365+
return NULL;
13131366
} else {
13141367
/* Real bundle */
13151368
if (stale_bundle(dst))
@@ -1673,6 +1726,171 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
16731726
return xdst;
16741727
}
16751728

1729+
static void xfrm_policy_queue_process(unsigned long arg)
1730+
{
1731+
int err = 0;
1732+
struct sk_buff *skb;
1733+
struct sock *sk;
1734+
struct dst_entry *dst;
1735+
struct net_device *dev;
1736+
struct xfrm_policy *pol = (struct xfrm_policy *)arg;
1737+
struct xfrm_policy_queue *pq = &pol->polq;
1738+
struct flowi fl;
1739+
struct sk_buff_head list;
1740+
1741+
spin_lock(&pq->hold_queue.lock);
1742+
skb = skb_peek(&pq->hold_queue);
1743+
dst = skb_dst(skb);
1744+
sk = skb->sk;
1745+
xfrm_decode_session(skb, &fl, dst->ops->family);
1746+
spin_unlock(&pq->hold_queue.lock);
1747+
1748+
dst_hold(dst->path);
1749+
dst = xfrm_lookup(xp_net(pol), dst->path, &fl,
1750+
sk, 0);
1751+
if (IS_ERR(dst))
1752+
goto purge_queue;
1753+
1754+
if (dst->flags & DST_XFRM_QUEUE) {
1755+
dst_release(dst);
1756+
1757+
if (pq->timeout >= XFRM_QUEUE_TMO_MAX)
1758+
goto purge_queue;
1759+
1760+
pq->timeout = pq->timeout << 1;
1761+
mod_timer(&pq->hold_timer, jiffies + pq->timeout);
1762+
return;
1763+
}
1764+
1765+
dst_release(dst);
1766+
1767+
__skb_queue_head_init(&list);
1768+
1769+
spin_lock(&pq->hold_queue.lock);
1770+
pq->timeout = 0;
1771+
skb_queue_splice_init(&pq->hold_queue, &list);
1772+
spin_unlock(&pq->hold_queue.lock);
1773+
1774+
while (!skb_queue_empty(&list)) {
1775+
skb = __skb_dequeue(&list);
1776+
1777+
xfrm_decode_session(skb, &fl, skb_dst(skb)->ops->family);
1778+
dst_hold(skb_dst(skb)->path);
1779+
dst = xfrm_lookup(xp_net(pol), skb_dst(skb)->path,
1780+
&fl, skb->sk, 0);
1781+
if (IS_ERR(dst)) {
1782+
dev_put(skb->dev);
1783+
kfree_skb(skb);
1784+
continue;
1785+
}
1786+
1787+
nf_reset(skb);
1788+
skb_dst_drop(skb);
1789+
skb_dst_set(skb, dst);
1790+
1791+
dev = skb->dev;
1792+
err = dst_output(skb);
1793+
dev_put(dev);
1794+
}
1795+
1796+
return;
1797+
1798+
purge_queue:
1799+
pq->timeout = 0;
1800+
xfrm_queue_purge(&pq->hold_queue);
1801+
}
1802+
1803+
static int xdst_queue_output(struct sk_buff *skb)
1804+
{
1805+
unsigned long sched_next;
1806+
struct dst_entry *dst = skb_dst(skb);
1807+
struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
1808+
struct xfrm_policy_queue *pq = &xdst->pols[0]->polq;
1809+
1810+
if (pq->hold_queue.qlen > XFRM_MAX_QUEUE_LEN) {
1811+
kfree_skb(skb);
1812+
return -EAGAIN;
1813+
}
1814+
1815+
skb_dst_force(skb);
1816+
dev_hold(skb->dev);
1817+
1818+
spin_lock_bh(&pq->hold_queue.lock);
1819+
1820+
if (!pq->timeout)
1821+
pq->timeout = XFRM_QUEUE_TMO_MIN;
1822+
1823+
sched_next = jiffies + pq->timeout;
1824+
1825+
if (del_timer(&pq->hold_timer)) {
1826+
if (time_before(pq->hold_timer.expires, sched_next))
1827+
sched_next = pq->hold_timer.expires;
1828+
}
1829+
1830+
__skb_queue_tail(&pq->hold_queue, skb);
1831+
mod_timer(&pq->hold_timer, sched_next);
1832+
1833+
spin_unlock_bh(&pq->hold_queue.lock);
1834+
1835+
return 0;
1836+
}
1837+
1838+
static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
1839+
struct dst_entry *dst,
1840+
const struct flowi *fl,
1841+
int num_xfrms,
1842+
u16 family)
1843+
{
1844+
int err;
1845+
struct net_device *dev;
1846+
struct dst_entry *dst1;
1847+
struct xfrm_dst *xdst;
1848+
1849+
xdst = xfrm_alloc_dst(net, family);
1850+
if (IS_ERR(xdst))
1851+
return xdst;
1852+
1853+
if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0 ||
1854+
(fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP))
1855+
return xdst;
1856+
1857+
dst1 = &xdst->u.dst;
1858+
dst_hold(dst);
1859+
xdst->route = dst;
1860+
1861+
dst_copy_metrics(dst1, dst);
1862+
1863+
dst1->obsolete = DST_OBSOLETE_FORCE_CHK;
1864+
dst1->flags |= DST_HOST | DST_XFRM_QUEUE;
1865+
dst1->lastuse = jiffies;
1866+
1867+
dst1->input = dst_discard;
1868+
dst1->output = xdst_queue_output;
1869+
1870+
dst_hold(dst);
1871+
dst1->child = dst;
1872+
dst1->path = dst;
1873+
1874+
xfrm_init_path((struct xfrm_dst *)dst1, dst, 0);
1875+
1876+
err = -ENODEV;
1877+
dev = dst->dev;
1878+
if (!dev)
1879+
goto free_dst;
1880+
1881+
err = xfrm_fill_dst(xdst, dev, fl);
1882+
if (err)
1883+
goto free_dst;
1884+
1885+
out:
1886+
return xdst;
1887+
1888+
free_dst:
1889+
dst_release(dst1);
1890+
xdst = ERR_PTR(err);
1891+
goto out;
1892+
}
1893+
16761894
static struct flow_cache_object *
16771895
xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
16781896
struct flow_cache_object *oldflo, void *ctx)
@@ -1751,7 +1969,7 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
17511969
/* We found policies, but there's no bundles to instantiate:
17521970
* either because the policy blocks, has no transformations or
17531971
* we could not build template (no xfrm_states).*/
1754-
xdst = xfrm_alloc_dst(net, family);
1972+
xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family);
17551973
if (IS_ERR(xdst)) {
17561974
xfrm_pols_put(pols, num_pols);
17571975
return ERR_CAST(xdst);
@@ -2359,6 +2577,9 @@ static int xfrm_bundle_ok(struct xfrm_dst *first)
23592577
(dst->dev && !netif_running(dst->dev)))
23602578
return 0;
23612579

2580+
if (dst->flags & DST_XFRM_QUEUE)
2581+
return 1;
2582+
23622583
last = NULL;
23632584

23642585
do {

0 commit comments

Comments
 (0)