diff options
author | Rémi Denis-Courmont <remi.denis-courmont@nokia.com> | 2010-09-15 08:30:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-16 00:31:33 -0400 |
commit | 507215f8d04f9e61f38c975e61d93bcafd30815f (patch) | |
tree | 79a88610eaf8abcc3f160ca0ced0a1b4e72dfd80 | |
parent | b6a563b2af4ec5b0363cf89869ba234c0e2cd3da (diff) |
Phonet: list subscribed resources via proc_fs
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/phonet/pn_dev.h | 1 | ||||
-rw-r--r-- | net/phonet/pn_dev.c | 2 | ||||
-rw-r--r-- | net/phonet/socket.c | 96 |
3 files changed, 99 insertions, 0 deletions
diff --git a/include/net/phonet/pn_dev.h b/include/net/phonet/pn_dev.h index 2d16783d5e20..13649eb57413 100644 --- a/include/net/phonet/pn_dev.h +++ b/include/net/phonet/pn_dev.h | |||
@@ -57,5 +57,6 @@ struct net_device *phonet_route_output(struct net *net, u8 daddr); | |||
57 | #define PN_NO_ADDR 0xff | 57 | #define PN_NO_ADDR 0xff |
58 | 58 | ||
59 | extern const struct file_operations pn_sock_seq_fops; | 59 | extern const struct file_operations pn_sock_seq_fops; |
60 | extern const struct file_operations pn_res_seq_fops; | ||
60 | 61 | ||
61 | #endif | 62 | #endif |
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index d0a429459370..947038ddd04c 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
@@ -373,6 +373,7 @@ int __init phonet_device_init(void) | |||
373 | if (err) | 373 | if (err) |
374 | return err; | 374 | return err; |
375 | 375 | ||
376 | proc_net_fops_create(&init_net, "pnresource", 0, &pn_res_seq_fops); | ||
376 | register_netdevice_notifier(&phonet_device_notifier); | 377 | register_netdevice_notifier(&phonet_device_notifier); |
377 | err = phonet_netlink_register(); | 378 | err = phonet_netlink_register(); |
378 | if (err) | 379 | if (err) |
@@ -385,6 +386,7 @@ void phonet_device_exit(void) | |||
385 | rtnl_unregister_all(PF_PHONET); | 386 | rtnl_unregister_all(PF_PHONET); |
386 | unregister_netdevice_notifier(&phonet_device_notifier); | 387 | unregister_netdevice_notifier(&phonet_device_notifier); |
387 | unregister_pernet_device(&phonet_net_ops); | 388 | unregister_pernet_device(&phonet_net_ops); |
389 | proc_net_remove(&init_net, "pnresource"); | ||
388 | } | 390 | } |
389 | 391 | ||
390 | int phonet_route_add(struct net_device *dev, u8 daddr) | 392 | int phonet_route_add(struct net_device *dev, u8 daddr) |
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index d4f41afc0583..6bf6e3c97d5c 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -654,3 +654,99 @@ void pn_sock_unbind_all_res(struct sock *sk) | |||
654 | match--; | 654 | match--; |
655 | } | 655 | } |
656 | } | 656 | } |
657 | |||
658 | #ifdef CONFIG_PROC_FS | ||
659 | static struct sock **pn_res_get_idx(struct seq_file *seq, loff_t pos) | ||
660 | { | ||
661 | struct net *net = seq_file_net(seq); | ||
662 | unsigned i; | ||
663 | |||
664 | if (!net_eq(net, &init_net)) | ||
665 | return NULL; | ||
666 | |||
667 | for (i = 0; i < 256; i++) { | ||
668 | if (pnres.sk[i] == NULL) | ||
669 | continue; | ||
670 | if (!pos) | ||
671 | return pnres.sk + i; | ||
672 | pos--; | ||
673 | } | ||
674 | return NULL; | ||
675 | } | ||
676 | |||
677 | static struct sock **pn_res_get_next(struct seq_file *seq, struct sock **sk) | ||
678 | { | ||
679 | struct net *net = seq_file_net(seq); | ||
680 | unsigned i; | ||
681 | |||
682 | BUG_ON(!net_eq(net, &init_net)); | ||
683 | |||
684 | for (i = (sk - pnres.sk) + 1; i < 256; i++) | ||
685 | if (pnres.sk[i]) | ||
686 | return pnres.sk + i; | ||
687 | return NULL; | ||
688 | } | ||
689 | |||
690 | static void *pn_res_seq_start(struct seq_file *seq, loff_t *pos) | ||
691 | __acquires(resource_mutex) | ||
692 | { | ||
693 | mutex_lock(&resource_mutex); | ||
694 | return *pos ? pn_res_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; | ||
695 | } | ||
696 | |||
697 | static void *pn_res_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
698 | { | ||
699 | struct sock **sk; | ||
700 | |||
701 | if (v == SEQ_START_TOKEN) | ||
702 | sk = pn_res_get_idx(seq, 0); | ||
703 | else | ||
704 | sk = pn_res_get_next(seq, v); | ||
705 | (*pos)++; | ||
706 | return sk; | ||
707 | } | ||
708 | |||
709 | static void pn_res_seq_stop(struct seq_file *seq, void *v) | ||
710 | __releases(resource_mutex) | ||
711 | { | ||
712 | mutex_unlock(&resource_mutex); | ||
713 | } | ||
714 | |||
715 | static int pn_res_seq_show(struct seq_file *seq, void *v) | ||
716 | { | ||
717 | int len; | ||
718 | |||
719 | if (v == SEQ_START_TOKEN) | ||
720 | seq_printf(seq, "%s%n", "rs uid inode", &len); | ||
721 | else { | ||
722 | struct sock **psk = v; | ||
723 | struct sock *sk = *psk; | ||
724 | |||
725 | seq_printf(seq, "%02X %5d %lu%n", | ||
726 | psk - pnres.sk, sock_i_uid(sk), sock_i_ino(sk), &len); | ||
727 | } | ||
728 | seq_printf(seq, "%*s\n", 63 - len, ""); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | static const struct seq_operations pn_res_seq_ops = { | ||
733 | .start = pn_res_seq_start, | ||
734 | .next = pn_res_seq_next, | ||
735 | .stop = pn_res_seq_stop, | ||
736 | .show = pn_res_seq_show, | ||
737 | }; | ||
738 | |||
739 | static int pn_res_open(struct inode *inode, struct file *file) | ||
740 | { | ||
741 | return seq_open_net(inode, file, &pn_res_seq_ops, | ||
742 | sizeof(struct seq_net_private)); | ||
743 | } | ||
744 | |||
745 | const struct file_operations pn_res_seq_fops = { | ||
746 | .owner = THIS_MODULE, | ||
747 | .open = pn_res_open, | ||
748 | .read = seq_read, | ||
749 | .llseek = seq_lseek, | ||
750 | .release = seq_release_net, | ||
751 | }; | ||
752 | #endif | ||