diff options
| author | Stephen Hemminger <shemminger@osdl.org> | 2003-08-07 06:29:48 +1000 |
|---|---|---|
| committer | Stephen Hemminger <shemminger@osdl.org> | 2003-08-07 06:29:48 +1000 |
| commit | bdba9fe94c5852c8f4956709bd711e07108778b3 (patch) | |
| tree | 54013e452d6f1cd13cb860f0beae8847b25a500b | |
| parent | 6ae0b08d7fb678751ec27a2b22f38c771e9eed8f (diff) | |
[NET] Convert ROSE to seq_file
The existing ROSE /proc interface has no module owner, and doesn't check for
bounds overflow. Easier to just convert it to the seq_file wrapper functions.
This patch is against 2.6.0-test2 (offsets assume earlier patch).
| -rw-r--r-- | include/net/rose.h | 11 | ||||
| -rw-r--r-- | net/rose/af_rose.c | 104 | ||||
| -rw-r--r-- | net/rose/rose_route.c | 294 |
3 files changed, 266 insertions, 143 deletions
diff --git a/include/net/rose.h b/include/net/rose.h index 37e8176ee7d2..77270b795bfd 100644 --- a/include/net/rose.h +++ b/include/net/rose.h @@ -140,6 +140,9 @@ typedef struct { #define rose_sk(__sk) ((rose_cb *)(__sk)->sk_protinfo) +/* Magic value indicating first entry in /proc (ie header) */ +#define ROSE_PROC_START ((void *) 1) + /* af_rose.c */ extern ax25_address rose_callsign; extern int sysctl_rose_restart_request_timeout; @@ -154,7 +157,7 @@ extern int sysctl_rose_maximum_vcs; extern int sysctl_rose_window_size; extern int rosecmp(rose_address *, rose_address *); extern int rosecmpm(rose_address *, rose_address *, unsigned short); -extern char *rose2asc(rose_address *); +extern const char *rose2asc(const rose_address *); extern struct sock *rose_find_socket(unsigned int, struct rose_neigh *); extern void rose_kill_by_neigh(struct rose_neigh *); extern unsigned int rose_new_lci(struct rose_neigh *); @@ -193,6 +196,9 @@ extern void rose_enquiry_response(struct sock *); /* rose_route.c */ extern struct rose_neigh *rose_loopback_neigh; +extern struct file_operations rose_neigh_fops; +extern struct file_operations rose_nodes_fops; +extern struct file_operations rose_routes_fops; extern int rose_add_loopback_neigh(void); extern int rose_add_loopback_node(rose_address *); @@ -207,9 +213,6 @@ extern struct rose_neigh *rose_get_neigh(rose_address *, unsigned char *, unsign extern int rose_rt_ioctl(unsigned int, void *); extern void rose_link_failed(ax25_cb *, int); extern int rose_route_frame(struct sk_buff *, ax25_cb *); -extern int rose_nodes_get_info(char *, char **, off_t, int); -extern int rose_neigh_get_info(char *, char **, off_t, int); -extern int rose_routes_get_info(char *, char **, off_t, int); extern void rose_rt_free(void); /* rose_subr.c */ diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 96fc7d9a087d..d540328896ab 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -39,6 +39,7 @@ #include <linux/notifier.h> #include <net/rose.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <net/tcp.h> #include <net/ip.h> #include <net/arp.h> @@ -56,8 +57,8 @@ int sysctl_rose_link_fail_timeout = ROSE_DEFAULT_FAIL_TIMEOUT; int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC; int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE; -static HLIST_HEAD(rose_list); -static spinlock_t rose_list_lock = SPIN_LOCK_UNLOCKED; +HLIST_HEAD(rose_list); +spinlock_t rose_list_lock = SPIN_LOCK_UNLOCKED; static struct proto_ops rose_proto_ops; @@ -66,7 +67,7 @@ ax25_address rose_callsign; /* * Convert a ROSE address into text. */ -char *rose2asc(rose_address *addr) +const char *rose2asc(const rose_address *addr) { static char buffer[11]; @@ -1332,29 +1333,57 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return 0; } -static int rose_get_info(char *buffer, char **start, off_t offset, int length) +#ifdef CONFIG_PROC_FS +static void *rose_info_start(struct seq_file *seq, loff_t *pos) { + int i; struct sock *s; struct hlist_node *node; - struct net_device *dev; - const char *devname, *callsign; - int len = 0; - off_t pos = 0; - off_t begin = 0; spin_lock_bh(&rose_list_lock); + if (*pos == 0) + return ROSE_PROC_START; + + i = 1; + sk_for_each(s, node, &rose_list) { + if (i == *pos) + return s; + ++i; + } + return NULL; +} - len += sprintf(buffer, "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); +static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; - sk_for_each(s, node, &rose_list) { + return (v == ROSE_PROC_START) ? sk_head(&rose_list) + : sk_next((struct sock *)v); +} + +static void rose_info_stop(struct seq_file *seq, void *v) +{ + spin_unlock_bh(&rose_list_lock); +} + +static int rose_info_show(struct seq_file *seq, void *v) +{ + if (v == ROSE_PROC_START) + seq_puts(seq, + "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); + + else { + struct sock *s = v; rose_cb *rose = rose_sk(s); + const char *devname, *callsign; + const struct net_device *dev = rose->device; - if ((dev = rose->device) == NULL) + if (!dev) devname = "???"; else devname = dev->name; - - len += sprintf(buffer + len, "%-10s %-9s ", + + seq_printf(seq, "%-10s %-9s ", rose2asc(&rose->dest_addr), ax2asc(&rose->dest_call)); @@ -1363,7 +1392,8 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length) else callsign = ax2asc(&rose->source_call); - len += sprintf(buffer + len, "%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n", + seq_printf(seq, + "%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n", rose2asc(&rose->source_addr), callsign, devname, @@ -1383,27 +1413,32 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length) atomic_read(&s->sk_wmem_alloc), atomic_read(&s->sk_rmem_alloc), s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); - - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - - if (pos > offset + length) - break; } - spin_unlock_bh(&rose_list_lock); - *start = buffer + (offset - begin); - len -= (offset - begin); + return 0; +} - if (len > length) len = length; +static struct seq_operations rose_info_seqops = { + .start = rose_info_start, + .next = rose_info_next, + .stop = rose_info_stop, + .show = rose_info_show, +}; - return len; +static int rose_info_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &rose_info_seqops); } +static struct file_operations rose_info_fops = { + .owner = THIS_MODULE, + .open = rose_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#endif /* CONFIG_PROC_FS */ + static struct net_proto_family rose_family_ops = { .family = PF_ROSE, .create = rose_create, @@ -1499,10 +1534,11 @@ static int __init rose_proto_init(void) rose_add_loopback_neigh(); - proc_net_create("rose", 0, rose_get_info); - proc_net_create("rose_neigh", 0, rose_neigh_get_info); - proc_net_create("rose_nodes", 0, rose_nodes_get_info); - proc_net_create("rose_routes", 0, rose_routes_get_info); + proc_net_fops_create("rose", S_IRUGO, &rose_info_fops); + proc_net_fops_create("rose_neigh", S_IRUGO, &rose_neigh_fops); + proc_net_fops_create("rose_nodes", S_IRUGO, &rose_nodes_fops); + proc_net_fops_create("rose_routes", S_IRUGO, &rose_routes_fops); + return 0; } module_init(rose_proto_init); diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 88817bb1344f..9cc95f475b81 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -35,12 +35,13 @@ #include <linux/netfilter.h> #include <linux/init.h> #include <net/rose.h> +#include <linux/seq_file.h> static unsigned int rose_neigh_no = 1; static struct rose_node *rose_node_list; static spinlock_t rose_node_list_lock = SPIN_LOCK_UNLOCKED; -static struct rose_neigh *rose_neigh_list; +struct rose_neigh *rose_neigh_list; static spinlock_t rose_neigh_list_lock = SPIN_LOCK_UNLOCKED; static struct rose_route *rose_route_list; static spinlock_t rose_route_list_lock = SPIN_LOCK_UNLOCKED; @@ -1066,165 +1067,248 @@ out: return res; } -int rose_nodes_get_info(char *buffer, char **start, off_t offset, int length) +#ifdef CONFIG_PROC_FS + +static void *rose_node_start(struct seq_file *seq, loff_t *pos) { struct rose_node *rose_node; - int len = 0; - off_t pos = 0; - off_t begin = 0; - int i; + int i = 1; spin_lock_bh(&rose_neigh_list_lock); + if (*pos == 0) + return ROSE_PROC_START; + + for (rose_node = rose_node_list; rose_node && i < *pos; + rose_node = rose_node->next, ++i); + + return (i == *pos) ? rose_node : NULL; +} - len += sprintf(buffer, "address mask n neigh neigh neigh\n"); +static void *rose_node_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + + return (v == ROSE_PROC_START) ? rose_node_list + : ((struct rose_node *)v)->next; +} - for (rose_node = rose_node_list; rose_node != NULL; rose_node = rose_node->next) { +static void rose_node_stop(struct seq_file *seq, void *v) +{ + spin_unlock_bh(&rose_neigh_list_lock); +} + +static int rose_node_show(struct seq_file *seq, void *v) +{ + int i; + + if (v == ROSE_PROC_START) + seq_puts(seq, "address mask n neigh neigh neigh\n"); + else { + const struct rose_node *rose_node = v; /* if (rose_node->loopback) { - len += sprintf(buffer + len, "%-10s %04d 1 loopback\n", + seq_printf(seq, "%-10s %04d 1 loopback\n", rose2asc(&rose_node->address), rose_node->mask); } else { */ - len += sprintf(buffer + len, "%-10s %04d %d", + seq_printf(seq, "%-10s %04d %d", rose2asc(&rose_node->address), rose_node->mask, rose_node->count); for (i = 0; i < rose_node->count; i++) - len += sprintf(buffer + len, " %05d", + seq_printf(seq, " %05d", rose_node->neighbour[i]->number); - len += sprintf(buffer + len, "\n"); + seq_puts(seq, "\n"); /* } */ - - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - - if (pos > offset + length) - break; } - spin_unlock_bh(&rose_neigh_list_lock); - - *start = buffer + (offset - begin); - len -= (offset - begin); + return 0; +} - if (len > length) - len = length; +static struct seq_operations rose_node_seqops = { + .start = rose_node_start, + .next = rose_node_next, + .stop = rose_node_stop, + .show = rose_node_show, +}; - return len; +static int rose_nodes_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &rose_node_seqops); } -int rose_neigh_get_info(char *buffer, char **start, off_t offset, int length) +struct file_operations rose_nodes_fops = { + .owner = THIS_MODULE, + .open = rose_nodes_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void *rose_neigh_start(struct seq_file *seq, loff_t *pos) { struct rose_neigh *rose_neigh; - int len = 0; - off_t pos = 0; - off_t begin = 0; - int i; + int i = 1; spin_lock_bh(&rose_neigh_list_lock); + if (*pos == 0) + return ROSE_PROC_START; - len += sprintf(buffer, "addr callsign dev count use mode restart t0 tf digipeaters\n"); + for (rose_neigh = rose_neigh_list; rose_neigh && i < *pos; + rose_neigh = rose_neigh->next, ++i); - for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) { - /* if (!rose_neigh->loopback) { */ - len += sprintf(buffer + len, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu", - rose_neigh->number, - (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->callsign), - rose_neigh->dev ? rose_neigh->dev->name : "???", - rose_neigh->count, - rose_neigh->use, - (rose_neigh->dce_mode) ? "DCE" : "DTE", - (rose_neigh->restarted) ? "yes" : "no", - ax25_display_timer(&rose_neigh->t0timer) / HZ, - ax25_display_timer(&rose_neigh->ftimer) / HZ); - - if (rose_neigh->digipeat != NULL) { - for (i = 0; i < rose_neigh->digipeat->ndigi; i++) - len += sprintf(buffer + len, " %s", ax2asc(&rose_neigh->digipeat->calls[i])); - } + return (i == *pos) ? rose_neigh : NULL; +} - len += sprintf(buffer + len, "\n"); +static void *rose_neigh_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + + return (v == ROSE_PROC_START) ? rose_neigh_list + : ((struct rose_neigh *)v)->next; +} - pos = begin + len; +static void rose_neigh_stop(struct seq_file *seq, void *v) +{ + spin_unlock_bh(&rose_neigh_list_lock); +} - if (pos < offset) { - len = 0; - begin = pos; - } +static int rose_neigh_show(struct seq_file *seq, void *v) +{ + int i; - if (pos > offset + length) - break; - /* } */ - } + if (v == ROSE_PROC_START) + seq_puts(seq, + "addr callsign dev count use mode restart t0 tf digipeaters\n"); + else { + struct rose_neigh *rose_neigh = v; - spin_unlock_bh(&rose_neigh_list_lock); + /* if (!rose_neigh->loopback) { */ + seq_printf(seq, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu", + rose_neigh->number, + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->callsign), + rose_neigh->dev ? rose_neigh->dev->name : "???", + rose_neigh->count, + rose_neigh->use, + (rose_neigh->dce_mode) ? "DCE" : "DTE", + (rose_neigh->restarted) ? "yes" : "no", + ax25_display_timer(&rose_neigh->t0timer) / HZ, + ax25_display_timer(&rose_neigh->ftimer) / HZ); + + if (rose_neigh->digipeat != NULL) { + for (i = 0; i < rose_neigh->digipeat->ndigi; i++) + seq_printf(seq, " %s", ax2asc(&rose_neigh->digipeat->calls[i])); + } + + seq_puts(seq, "\n"); + } + return 0; +} - *start = buffer + (offset - begin); - len -= (offset - begin); - if (len > length) - len = length; +static struct seq_operations rose_neigh_seqops = { + .start = rose_neigh_start, + .next = rose_neigh_next, + .stop = rose_neigh_stop, + .show = rose_neigh_show, +}; - return len; +static int rose_neigh_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &rose_neigh_seqops); } -int rose_routes_get_info(char *buffer, char **start, off_t offset, int length) +struct file_operations rose_neigh_fops = { + .owner = THIS_MODULE, + .open = rose_neigh_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + + +static void *rose_route_start(struct seq_file *seq, loff_t *pos) { struct rose_route *rose_route; - int len = 0; - off_t pos = 0; - off_t begin = 0; + int i = 1; spin_lock_bh(&rose_route_list_lock); + if (*pos == 0) + return ROSE_PROC_START; - len += sprintf(buffer, "lci address callsign neigh <-> lci address callsign neigh\n"); + for (rose_route = rose_route_list; rose_route && i < *pos; + rose_route = rose_route->next, ++i); - for (rose_route = rose_route_list; rose_route != NULL; rose_route = rose_route->next) { - if (rose_route->neigh1 != NULL) { - len += sprintf(buffer + len, "%3.3X %-10s %-9s %05d ", - rose_route->lci1, - rose2asc(&rose_route->src_addr), - ax2asc(&rose_route->src_call), - rose_route->neigh1->number); - } else { - len += sprintf(buffer + len, "000 * * 00000 "); - } + return (i == *pos) ? rose_route : NULL; +} + +static void *rose_route_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + + return (v == ROSE_PROC_START) ? rose_route_list + : ((struct rose_route *)v)->next; +} - if (rose_route->neigh2 != NULL) { - len += sprintf(buffer + len, "%3.3X %-10s %-9s %05d\n", +static void rose_route_stop(struct seq_file *seq, void *v) +{ + spin_unlock_bh(&rose_route_list_lock); +} + +static int rose_route_show(struct seq_file *seq, void *v) +{ + if (v == ROSE_PROC_START) + seq_puts(seq, + "lci address callsign neigh <-> lci address callsign neigh\n"); + else { + struct rose_route *rose_route = v; + + if (rose_route->neigh1) + seq_printf(seq, + "%3.3X %-10s %-9s %05d ", + rose_route->lci1, + rose2asc(&rose_route->src_addr), + ax2asc(&rose_route->src_call), + rose_route->neigh1->number); + else + seq_puts(seq, + "000 * * 00000 "); + + if (rose_route->neigh2) + seq_printf(seq, + "%3.3X %-10s %-9s %05d\n", rose_route->lci2, rose2asc(&rose_route->dest_addr), ax2asc(&rose_route->dest_call), rose_route->neigh2->number); - } else { - len += sprintf(buffer + len, "000 * * 00000\n"); - } - - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; + else + seq_puts(seq, + "000 * * 00000\n"); } + return 0; +} - if (pos > offset + length) - break; - } +static struct seq_operations rose_route_seqops = { + .start = rose_route_start, + .next = rose_route_next, + .stop = rose_route_stop, + .show = rose_route_show, +}; - spin_unlock_bh(&rose_route_list_lock); - - *start = buffer + (offset - begin); - len -= (offset - begin); +static int rose_route_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &rose_route_seqops); +} - if (len > length) - len = length; +struct file_operations rose_routes_fops = { + .owner = THIS_MODULE, + .open = rose_route_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; - return len; -} +#endif /* CONFIG_PROC_FS */ /* * Release all memory associated with ROSE routing structures. |
