Skip to content

Commit

Permalink
[XFRM]: Export SPD info
Browse files Browse the repository at this point in the history
With this patch you can use iproute2 in user space to efficiently see
how many policies exist in different directions.

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jamal Hadi Salim authored and davem330 committed Apr 29, 2007
1 parent 5632c51 commit ecfd6b1
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 1 deletion.
35 changes: 35 additions & 0 deletions include/linux/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ enum {
#define XFRM_MSG_NEWSADINFO XFRM_MSG_NEWSADINFO
XFRM_MSG_GETSADINFO,
#define XFRM_MSG_GETSADINFO XFRM_MSG_GETSADINFO

XFRM_MSG_NEWSPDINFO,
#define XFRM_MSG_NEWSPDINFO XFRM_MSG_NEWSPDINFO
XFRM_MSG_GETSPDINFO,
#define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO
__XFRM_MSG_MAX
};
#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
Expand Down Expand Up @@ -290,6 +295,36 @@ enum xfrm_sadattr_type_t {
#define XFRMA_SAD_MAX (__XFRMA_SAD_MAX - 1)
};

/* SPD Table filter flags */
enum xfrm_spd_ftype_t {
XFRM_SPD_UNSPEC,
XFRM_SPD_HMASK=1,
XFRM_SPD_HMAX=2,
XFRM_SPD_ICNT=4,
XFRM_SPD_OCNT=8,
XFRM_SPD_FCNT=16,
XFRM_SPD_ISCNT=32,
XFRM_SPD_OSCNT=64,
XFRM_SPD_FSCNT=128,
__XFRM_SPD_MAX

#define XFRM_SPD_MAX (__XFRM_SPD_MAX - 1)
};
enum xfrm_spdattr_type_t {
XFRMA_SPD_UNSPEC,
XFRMA_SPDHMASK,
XFRMA_SPDHMAX,
XFRMA_SPDICNT,
XFRMA_SPDOCNT,
XFRMA_SPDFCNT,
XFRMA_SPDISCNT,
XFRMA_SPDOSCNT,
XFRMA_SPDFSCNT,
__XFRMA_SPD_MAX

#define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1)
};

struct xfrm_usersa_info {
struct xfrm_selector sel;
struct xfrm_id id;
Expand Down
13 changes: 13 additions & 0 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,18 @@ struct xfrm_sadinfo
u32 sadhmcnt; /* max allowed hash bkts */
u32 sadcnt; /* current running count */
};

struct xfrm_spdinfo
{
u32 incnt;
u32 outcnt;
u32 fwdcnt;
u32 inscnt;
u32 outscnt;
u32 fwdscnt;
u32 spdhcnt;
u32 spdhmcnt;
};
#ifdef CONFIG_AUDITSYSCALL
extern void xfrm_audit_log(uid_t auid, u32 secid, int type, int result,
struct xfrm_policy *xp, struct xfrm_state *x);
Expand Down Expand Up @@ -946,6 +958,7 @@ extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct xfrm_sadinfo *si);
extern void xfrm_spd_getinfo(struct xfrm_spdinfo *si);
extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
extern void xfrm_replay_notify(struct xfrm_state *x, int event);
Expand Down
16 changes: 15 additions & 1 deletion net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,8 +579,22 @@ static inline int xfrm_byidx_should_resize(int total)
return 0;
}

static DEFINE_MUTEX(hash_resize_mutex);
void xfrm_spd_getinfo(struct xfrm_spdinfo *si)
{
read_lock_bh(&xfrm_policy_lock);
si->incnt = xfrm_policy_count[XFRM_POLICY_IN];
si->outcnt = xfrm_policy_count[XFRM_POLICY_OUT];
si->fwdcnt = xfrm_policy_count[XFRM_POLICY_FWD];
si->inscnt = xfrm_policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX];
si->outscnt = xfrm_policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX];
si->fwdscnt = xfrm_policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX];
si->spdhcnt = xfrm_idx_hmask;
si->spdhmcnt = xfrm_policy_hashmax;
read_unlock_bh(&xfrm_policy_lock);
}
EXPORT_SYMBOL(xfrm_spd_getinfo);

static DEFINE_MUTEX(hash_resize_mutex);
static void xfrm_hash_resize(struct work_struct *__unused)
{
int dir, total;
Expand Down
77 changes: 77 additions & 0 deletions net/xfrm/xfrm_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,81 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
return skb;
}

static int build_spdinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
{
struct xfrm_spdinfo si;
struct nlmsghdr *nlh;
u32 *f;

nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0);
if (nlh == NULL) /* shouldnt really happen ... */
return -EMSGSIZE;

f = nlmsg_data(nlh);
*f = flags;
xfrm_spd_getinfo(&si);

if (flags & XFRM_SPD_HMASK)
NLA_PUT_U32(skb, XFRMA_SPDHMASK, si.spdhcnt);
if (flags & XFRM_SPD_HMAX)
NLA_PUT_U32(skb, XFRMA_SPDHMAX, si.spdhmcnt);
if (flags & XFRM_SPD_ICNT)
NLA_PUT_U32(skb, XFRMA_SPDICNT, si.incnt);
if (flags & XFRM_SPD_OCNT)
NLA_PUT_U32(skb, XFRMA_SPDOCNT, si.outcnt);
if (flags & XFRM_SPD_FCNT)
NLA_PUT_U32(skb, XFRMA_SPDFCNT, si.fwdcnt);
if (flags & XFRM_SPD_ISCNT)
NLA_PUT_U32(skb, XFRMA_SPDISCNT, si.inscnt);
if (flags & XFRM_SPD_OSCNT)
NLA_PUT_U32(skb, XFRMA_SPDOSCNT, si.inscnt);
if (flags & XFRM_SPD_FSCNT)
NLA_PUT_U32(skb, XFRMA_SPDFSCNT, si.inscnt);

return nlmsg_end(skb, nlh);

nla_put_failure:
nlmsg_cancel(skb, nlh);
return -EMSGSIZE;
}

static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtattr **xfrma)
{
struct sk_buff *r_skb;
u32 *flags = NLMSG_DATA(nlh);
u32 spid = NETLINK_CB(skb).pid;
u32 seq = nlh->nlmsg_seq;
int len = NLMSG_LENGTH(sizeof(u32));


if (*flags & XFRM_SPD_HMASK)
len += RTA_SPACE(sizeof(u32));
if (*flags & XFRM_SPD_HMAX)
len += RTA_SPACE(sizeof(u32));
if (*flags & XFRM_SPD_ICNT)
len += RTA_SPACE(sizeof(u32));
if (*flags & XFRM_SPD_OCNT)
len += RTA_SPACE(sizeof(u32));
if (*flags & XFRM_SPD_FCNT)
len += RTA_SPACE(sizeof(u32));
if (*flags & XFRM_SPD_ISCNT)
len += RTA_SPACE(sizeof(u32));
if (*flags & XFRM_SPD_OSCNT)
len += RTA_SPACE(sizeof(u32));
if (*flags & XFRM_SPD_FSCNT)
len += RTA_SPACE(sizeof(u32));

r_skb = alloc_skb(len, GFP_ATOMIC);
if (r_skb == NULL)
return -ENOMEM;

if (build_spdinfo(r_skb, spid, seq, *flags) < 0)
BUG();

return nlmsg_unicast(xfrm_nl, r_skb, spid);
}

static int build_sadinfo(struct sk_buff *skb, u32 pid, u32 seq, u32 flags)
{
struct xfrm_sadinfo si;
Expand Down Expand Up @@ -1879,6 +1954,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
[XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
[XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = NLMSG_LENGTH(sizeof(u32)),
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = NLMSG_LENGTH(sizeof(u32)),
};

#undef XMSGSIZE
Expand Down Expand Up @@ -1907,6 +1983,7 @@ static struct xfrm_link {
[XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae },
[XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate },
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo },
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo },
};

static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
Expand Down

0 comments on commit ecfd6b1

Please sign in to comment.