From cbd4016670515779a665e1e5d200d507ee7de993 Mon Sep 17 00:00:00 2001 From: Masahide NAKAMURA Date: Tue, 24 Apr 2007 12:11:47 +0900 Subject: [PATCH] [PATCH] [XFRM]: Show bundle cache information. Outbound transformation makes bundle cache as stackable destination (dst) and binds it to policy. This interface shows it as /proc/net/xfrm/bundle for developers. Signed-off-by: Masahide NAKAMURA --- net/xfrm/xfrm_proc.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 247 insertions(+), 0 deletions(-) diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index 7b55334..598f433 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -6,12 +6,249 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include +#include +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#include +#endif +#include + +#define XFRM_DEBUG 2 + +#if XFRM_DEBUG >= 1 +#define ENABLE_ROUTE +#include +#include +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#include +#endif +#endif + +#if XFRM_DEBUG >= 2 +#define ENABLE_NEIGHBOR +#include +#endif #ifdef CONFIG_PROC_FS +#ifdef ENABLE_NEIGHBOR +static int __xfrm_bundle_neigh_show(struct seq_file *seq, struct neighbour *n) +{ + int i; + + seq_printf(seq, " neigh %p %02x ", n, n->type); + + for (i = 0; i < sizeof(n->ha); i++) + seq_printf(seq, "%02x", n->ha[i]); + + return 0; +} + +static int xfrm_bundle_neigh_show(struct seq_file *seq, struct neighbour *n) +{ + int err = 0; + + if (n) { + read_lock(&n->lock); + err = __xfrm_bundle_neigh_show(seq, n); + read_unlock(&n->lock); + } + + return err; +} +#else +static inline int xfrm_bundle_neigh_show(struct seq_file *seq, + struct neighbour *n) +{ + return 0; +} +#endif + +#ifdef ENABLE_ROUTE +static int __xfrm_bundle_route_show(struct seq_file *seq, + struct xfrm_dst *xdst) +{ + u16 family; + + if (xdst->u.dst.ops) + family = xdst->u.dst.ops->family; + else + family = AF_UNSPEC; + + seq_printf(seq, " route %04x", family); + + switch (family) { + case AF_INET: + { + struct rtable *rt = &xdst->u.rt; + + /* XXX: It seems we have still missing things to identify + * entry i.e. table id and prefix length (network mask) + * for xfrm_dst. + */ + seq_printf(seq, " %08x %08x", rt->rt_dst, rt->rt_src); + seq_printf(seq, " %08x %s", rt->rt_gateway, + ((rt->idev && rt->idev->dev) ? + rt->idev->dev->name : "null")); + seq_printf(seq, " %04x", rt->rt_flags); + break; + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + { + struct rt6_info *rt6i = &xdst->u.rt6; + + seq_printf(seq, " %08x", rt6i->rt6i_table ? + rt6i->rt6i_table->tb6_id : RT_TABLE_UNSPEC); + seq_printf(seq, " " NIP6_SEQFMT " %02x " NIP6_SEQFMT " %02x", + NIP6(rt6i->rt6i_dst.addr), rt6i->rt6i_dst.plen, + NIP6(rt6i->rt6i_src.addr), rt6i->rt6i_src.plen); + seq_printf(seq, " " NIP6_SEQFMT " %s", + NIP6(rt6i->rt6i_gateway), + ((rt6i->rt6i_idev && rt6i->rt6i_idev->dev) ? + rt6i->rt6i_idev->dev->name : "null")); + seq_printf(seq, " %04x %08x", rt6i->rt6i_flags, + (rt6i->rt6i_node ? rt6i->rt6i_node->fn_sernum : 0)); + break; + } +#endif + default: + break; + } + + return 0; +} +#else +static inline int __xfrm_bundle_route_show(struct seq_file *seq, + struct xfrm_dst *xdst) +{ + return 0; +} +#endif + +static int __xfrm_bundle_state_show(struct seq_file *seq, struct xfrm_state *x) +{ + seq_printf(seq, " state %p %02x %02x %04x", x, x->id.proto, + x->props.mode, x->props.family); + + switch (x->props.family) { + case AF_INET: + seq_printf(seq, " %08x %08x", x->props.saddr.a4, + x->id.daddr.a4); + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + seq_printf(seq, " " NIP6_SEQFMT " " NIP6_SEQFMT, + NIP6(*(struct in6_addr *)&x->props.saddr.a6), + NIP6(*(struct in6_addr *)&x->id.daddr.a6)); + break; +#endif + default: + goto end; + } + + seq_printf(seq, " %08x", ntohl(x->id.spi)); + + end: + return 0; +} + +static int xfrm_bundle_state_show(struct seq_file *seq, struct xfrm_state *x) +{ + int err = 0; + + if (x) { + spin_lock(&x->lock); + err = __xfrm_bundle_state_show(seq, x); + spin_unlock(&x->lock); + } + + return err; +} + +static int __xfrm_bundle_dst_show(struct seq_file *seq, struct xfrm_dst *xdst, + int bundles, int gen) +{ + seq_printf(seq, " %p %p %08x %08x %08x %08x %08x", + xdst, xdst->u.dst.child, bundles, gen, xdst->genid, + (gen ? xdst->route_cookie : 0), + (gen ? xdst->path_cookie : 0)); + + xfrm_bundle_state_show(seq, xdst->u.dst.xfrm); + __xfrm_bundle_route_show(seq, xdst); + xfrm_bundle_neigh_show(seq, xdst->u.dst.neighbour); + + seq_printf(seq, "\n"); + + return 0; +} + +static int __xfrm_bundle_policy_show(struct seq_file *seq, + struct xfrm_policy *xp, int dir) +{ + struct dst_entry *dst; + int bundles = 0; + + if (!xp->bundles) + goto end; + + seq_printf(seq, "%02x %02x %08x\n", xp->type, dir, xp->index); + + for (dst = xp->bundles; dst; dst = dst->next) { + struct dst_entry *d = dst; + int gen = 0; + + bundles++; + for (d = dst; d; d = d->child) { + struct xfrm_dst *xdst = (struct xfrm_dst*)d; + if (__xfrm_bundle_dst_show(seq, xdst, bundles, gen++)) + goto end; + } + } + + end: + return 0; +} + +static int xfrm_bundle_policy_show(struct xfrm_policy *xp, int dir, int count, + void *data) +{ + struct seq_file *seq = (struct seq_file *)data; + int err; + + read_lock_bh(&xp->lock); + err = __xfrm_bundle_policy_show(seq, xp, dir); + read_unlock_bh(&xp->lock); + + return err; +} + +static int xfrm_bundle_seq_show(struct seq_file *seq, void *v) +{ + xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, xfrm_bundle_policy_show, seq); +#ifdef CONFIG_XFRM_SUB_POLICY + xfrm_policy_walk(XFRM_POLICY_TYPE_SUB, xfrm_bundle_policy_show, seq); +#endif + return 0; +} + +static int xfrm_bundle_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, xfrm_bundle_seq_show, NULL); +} + +static struct file_operations proc_net_xfrm_bundle_seq_fops = { + .owner = THIS_MODULE, + .open = xfrm_bundle_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static struct proc_dir_entry *proc_net_xfrm; +static struct proc_dir_entry *proc_net_xfrm_bundle; int __init xfrm_proc_init(void) { @@ -21,9 +258,18 @@ int __init xfrm_proc_init(void) if (!proc_net_xfrm) goto proc_net_xfrm_fail; + proc_net_xfrm_bundle = create_proc_entry("bundle", S_IRUGO, + proc_net_xfrm); + if (!proc_net_xfrm_bundle) + goto proc_net_xfrm_bundle_fail; + + proc_net_xfrm_bundle->proc_fops = &proc_net_xfrm_bundle_seq_fops; + out: return rc; + proc_net_xfrm_bundle_fail: + remove_proc_entry("xfrm", proc_net); proc_net_xfrm_fail: rc = -ENOMEM; goto out; @@ -32,6 +278,7 @@ int __init xfrm_proc_init(void) #if 0 void xfrm_proc_exit(void) { + remove_proc_entry("bundle", proc_net_xfrm); remove_proc_entry("xfrm", proc_net); } #endif -- 1.4.3.GIT