Import 1.3.17
[davej-history.git] / fs / proc / net.c
blob56bcfe58dd29f937a456ab94a172f150d45b46cc
1 /*
2 * linux/fs/proc/net.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
6 * gjh 3/'93 heim@peanuts.informatik.uni-tuebingen.de (Gerald J. Heim)
7 * most of this file is stolen from base.c
8 * it works, but you shouldn't use it as a guideline
9 * for new proc-fs entries. once i'll make it better.
10 * fvk 3/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
11 * cleaned up the whole thing, moved "net" specific code to
12 * the NET kernel layer (where it belonged in the first place).
13 * Michael K. Johnson (johnsonm@stolaf.edu) 3/93
14 * Added support from my previous inet.c. Cleaned things up
15 * quite a bit, modularized the code.
16 * fvk 4/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen)
17 * Renamed "route_get_info()" to "rt_get_info()" for consistency.
18 * Alan Cox (gw4pts@gw4pts.ampr.org) 4/94
19 * Dusted off the code and added IPX. Fixed the 4K limit.
20 * Erik Schoenfelder (schoenfr@ibr.cs.tu-bs.de)
21 * /proc/net/snmp.
22 * Alan Cox (gw4pts@gw4pts.ampr.org) 1/95
23 * Added Appletalk slots
25 * proc net directory handling functions
27 #include <linux/autoconf.h>
29 #include <asm/segment.h>
31 #include <linux/errno.h>
32 #include <linux/sched.h>
33 #include <linux/proc_fs.h>
34 #include <linux/stat.h>
35 #include <linux/fcntl.h>
36 #include <linux/config.h>
37 #include <linux/mm.h>
39 /* forward references */
40 static intproc_readnet(struct inode * inode,struct file * file,
41 char* buf,int count);
42 static intproc_readnetdir(struct inode *,struct file *,
43 void*, filldir_t filldir);
44 static intproc_lookupnet(struct inode *,const char*,int,struct inode **);
46 static struct file_operations proc_net_operations = {
47 NULL,/* lseek - default */
48 proc_readnet,/* read - bad */
49 NULL,/* write - bad */
50 proc_readnetdir,/* readdir */
51 NULL,/* select - default */
52 NULL,/* ioctl - default */
53 NULL,/* mmap */
54 NULL,/* no special open code */
55 NULL,/* no special release code */
56 NULL /* can't fsync */
60 * proc directories can do almost nothing..
62 struct inode_operations proc_net_inode_operations = {
63 &proc_net_operations,/* default net directory file-ops */
64 NULL,/* create */
65 proc_lookupnet,/* lookup */
66 NULL,/* link */
67 NULL,/* unlink */
68 NULL,/* symlink */
69 NULL,/* mkdir */
70 NULL,/* rmdir */
71 NULL,/* mknod */
72 NULL,/* rename */
73 NULL,/* readlink */
74 NULL,/* follow_link */
75 NULL,/* bmap */
76 NULL,/* truncate */
77 NULL /* permission */
80 #define NR_MAX_PROC_NET_DIR 100
81 static struct proc_dir_entry *net_dir[NR_MAX_PROC_NET_DIR] = {
82 NULL,
85 static int nr_net_direntry =0;
87 intproc_net_register(struct proc_dir_entry *dp)
89 int i;
91 for(i =0; net_dir[i] != NULL; ++i ) ;
93 if(i >= NR_MAX_PROC_NET_DIR)
94 return-ENOMEM;
96 net_dir[i] = dp;
97 net_dir[i+1] = NULL;/* Just make sure.. */
98 ++nr_net_direntry;
99 return i;
102 intproc_net_unregister(int ino)
104 int i;
105 for(i =0; net_dir[i] != NULL && i < nr_net_direntry; ++i)
106 if(net_dir[i]->low_ino == ino) {
107 for( ; net_dir[i] != NULL; ++i )
108 net_dir[i] = net_dir[i+1];
109 --nr_net_direntry;
110 return0;
112 return-ENOENT;
115 static intdir_get_info(char* a,char** b, off_t d,int e,int f)
117 return-EISDIR;
120 voidproc_net_init(void)
122 static struct proc_dir_entry
123 nd_thisdir = { PROC_NET, dir_get_info,1,"."},
124 nd_rootdir = { PROC_ROOT_INO, dir_get_info,1,".."};
125 static int already =0;
127 if(already)return;
128 already =1;
130 proc_net_register(&nd_thisdir);
131 proc_net_register(&nd_rootdir);
135 static intproc_lookupnet(struct inode * dir,const char* name,int len,
136 struct inode ** result)
138 struct proc_dir_entry **de;
140 *result = NULL;
141 if(!dir)
142 return-ENOENT;
143 if(!S_ISDIR(dir->i_mode)) {
144 iput(dir);
145 return-ENOENT;
147 for(de = net_dir ; (*de)->name ; de++) {
148 if(!proc_match(len, name, *de))
149 continue;
150 *result =iget(dir->i_sb, (*de)->low_ino);
151 iput(dir);
152 if(!*result)
153 return-ENOENT;
154 return0;
156 iput(dir);
157 return-ENOENT;
160 static intproc_readnetdir(struct inode * inode,struct file * filp,
161 void* dirent, filldir_t filldir)
163 struct proc_dir_entry * de;
164 unsigned int ino;
166 if(!inode || !S_ISDIR(inode->i_mode))
167 return-EBADF;
168 ino = inode->i_ino;
169 while(((unsigned) filp->f_pos) < nr_net_direntry) {
170 de = net_dir[filp->f_pos];
171 if(filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) <0)
172 break;
173 filp->f_pos++;
175 return0;
179 #define PROC_BLOCK_SIZE (3*1024)/* 4K page size but our output routines use some slack for overruns */
181 static intproc_readnet(struct inode * inode,struct file * file,
182 char* buf,int count)
184 char* page;
185 unsigned int ino;
186 int bytes=count;
187 int i;
188 int copied=0;
189 char*start;
190 struct proc_dir_entry * dp;
192 if(count <0)
193 return-EINVAL;
194 ino = inode->i_ino;
195 for(i =0; ;i++) {
196 if(i >= NR_MAX_PROC_NET_DIR || (dp = net_dir[i]) == NULL)
197 return-EBADF;
198 if(dp->low_ino == ino)
199 break;
201 if(!(page = (char*)__get_free_page(GFP_KERNEL)))
202 return-ENOMEM;
204 while(bytes>0)
206 int length, thistime=bytes;
207 if(bytes > PROC_BLOCK_SIZE)
208 thistime=PROC_BLOCK_SIZE;
210 length = dp->get_info(page, &start,
211 file->f_pos,
212 thistime,
213 (file->f_flags & O_ACCMODE) == O_RDWR);
216 * We have been given a non page aligned block of
217 * the data we asked for + a bit. We have been given
218 * the start pointer and we know the length..
221 if(length <=0)
222 break;
224 * Copy the bytes
226 memcpy_tofs(buf+copied, start, length);
227 file->f_pos += length;/* Move down the file */
228 bytes -= length;
229 copied += length;
230 if(length<thistime)
231 break;/* End of file */
233 free_page((unsigned long) page);
234 return copied;
close