This source file includes following definitions.
- proc_net_register
- proc_net_unregister
- dir_get_info
- proc_net_init
- proc_lookupnet
- proc_readnetdir
- proc_readnet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <linux/autoconf.h>
28
29 #include <asm/segment.h>
30
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>
38
39
40 static int proc_readnet(struct inode * inode, struct file * file,
41 char * buf, int count);
42 static int proc_readnetdir(struct inode *, struct file *,
43 void *, filldir_t filldir);
44 static int proc_lookupnet(struct inode *,const char *,int,struct inode **);
45
46 static struct file_operations proc_net_operations = {
47 NULL,
48 proc_readnet,
49 NULL,
50 proc_readnetdir,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 NULL,
56 NULL
57 };
58
59
60
61
62 struct inode_operations proc_net_inode_operations = {
63 &proc_net_operations,
64 NULL,
65 proc_lookupnet,
66 NULL,
67 NULL,
68 NULL,
69 NULL,
70 NULL,
71 NULL,
72 NULL,
73 NULL,
74 NULL,
75 NULL,
76 NULL,
77 NULL
78 };
79
80 #define NR_MAX_PROC_NET_DIR 100
81 static struct proc_dir_entry *net_dir[NR_MAX_PROC_NET_DIR] = {
82 NULL,
83 };
84
85 static int nr_net_direntry = 0;
86
87 int proc_net_register(struct proc_dir_entry *dp)
88 {
89 int i;
90
91 for (i = 0; net_dir[i] != NULL; ++i ) ;
92
93 if (i >= NR_MAX_PROC_NET_DIR)
94 return -ENOMEM;
95
96 net_dir[i] = dp;
97 net_dir[i+1] = NULL;
98 ++nr_net_direntry;
99 return i;
100 }
101
102 int proc_net_unregister(int ino)
103 {
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 return 0;
111 }
112 return -ENOENT;
113 }
114
115 static int dir_get_info(char * a, char ** b, off_t d, int e, int f)
116 {
117 return -EISDIR;
118 }
119
120 void proc_net_init(void)
121 {
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;
126
127 if (already) return;
128 already = 1;
129
130 proc_net_register(&nd_thisdir);
131 proc_net_register(&nd_rootdir);
132 }
133
134
135 static int proc_lookupnet(struct inode * dir,const char * name, int len,
136 struct inode ** result)
137 {
138 struct proc_dir_entry **de;
139
140 *result = NULL;
141 if (!dir)
142 return -ENOENT;
143 if (!S_ISDIR(dir->i_mode)) {
144 iput(dir);
145 return -ENOENT;
146 }
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 return 0;
155 }
156 iput(dir);
157 return -ENOENT;
158 }
159
160 static int proc_readnetdir(struct inode * inode, struct file * filp,
161 void * dirent, filldir_t filldir)
162 {
163 struct proc_dir_entry * de;
164 unsigned int ino;
165
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++;
174 }
175 return 0;
176 }
177
178
179 #define PROC_BLOCK_SIZE (3*1024)
180
181 static int proc_readnet(struct inode * inode, struct file * file,
182 char * buf, int count)
183 {
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;
191
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;
200 }
201 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
202 return -ENOMEM;
203
204 while (bytes>0)
205 {
206 int length, thistime=bytes;
207 if (bytes > PROC_BLOCK_SIZE)
208 thistime=PROC_BLOCK_SIZE;
209
210 length = dp->get_info(page, &start,
211 file->f_pos,
212 thistime,
213 (file->f_flags & O_ACCMODE) == O_RDWR);
214
215
216
217
218
219
220
221 if (length <= 0)
222 break;
223
224
225
226 memcpy_tofs(buf+copied, start, length);
227 file->f_pos += length;
228 bytes -= length;
229 copied += length;
230 if (length<thistime)
231 break;
232 }
233 free_page((unsigned long) page);
234 return copied;
235 }