This source file includes following definitions.
- netlink_err
- netlink_write
- netlink_read
- netlink_lseek
- netlink_open
- netlink_release
- netlink_ioctl
- netlink_attach
- netlink_detach
- netlink_post
- init_module
- cleanup_module
- init_netlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/config.h>
15
16 #if defined(CONFIG_NETLINK) || defined(MODULE)
17 #ifdef MODULE
18 #include <linux/module.h>
19 #include <linux/version.h>
20 #else
21 #define MOD_INC_USE_COUNT
22 #define MOD_DEC_USE_COUNT
23 #endif
24
25 #include <linux/errno.h>
26 #include <linux/kernel.h>
27 #include <linux/major.h>
28 #include <linux/sched.h>
29 #include <linux/lp.h>
30 #include <linux/malloc.h>
31 #include <linux/ioport.h>
32 #include <linux/fcntl.h>
33 #include <linux/delay.h>
34 #include <linux/skbuff.h>
35
36 #include <net/netlink.h>
37
38 #include <asm/io.h>
39 #include <asm/segment.h>
40 #include <asm/system.h>
41
42 static int (*netlink_handler[MAX_LINKS])(struct sk_buff *skb);
43 static struct sk_buff_head skb_queue_rd[MAX_LINKS];
44 static int rdq_size[MAX_LINKS];
45 static struct wait_queue *read_space_wait[MAX_LINKS];
46
47 static int active_map = 0;
48 static int open_map = 0;
49
50
51
52
53
54
55
56
57
58 static int netlink_err(struct sk_buff *skb)
59 {
60 kfree_skb(skb, FREE_READ);
61 return -EUNATCH;
62 }
63
64
65
66
67
68 static int netlink_write(struct inode * inode, struct file * file, const char * buf, int count)
69 {
70 unsigned int minor = MINOR(inode->i_rdev);
71 struct sk_buff *skb;
72 skb=alloc_skb(count, GFP_KERNEL);
73 memcpy_fromfs(skb_put(skb,count),buf, count);
74 return (netlink_handler[minor])(skb);
75 }
76
77
78
79
80
81 static int netlink_read(struct inode * inode, struct file * file, char * buf, int count)
82 {
83 unsigned int minor = MINOR(inode->i_rdev);
84 struct sk_buff *skb;
85 cli();
86 while((skb=skb_dequeue(&skb_queue_rd[minor]))==NULL)
87 {
88 if(file->f_flags&O_NONBLOCK)
89 {
90 sti();
91 return -EWOULDBLOCK;
92 }
93 interruptible_sleep_on(&read_space_wait[minor]);
94 if(current->signal & ~current->blocked)
95 {
96 sti();
97 return -ERESTARTSYS;
98 }
99 }
100 rdq_size[minor]-=skb->len;
101 sti();
102 if(skb->len<count)
103 count=skb->len;
104 memcpy_tofs(buf,skb->data,count);
105 kfree_skb(skb, FREE_READ);
106 return count;
107 }
108
109 static int netlink_lseek(struct inode * inode, struct file * file,
110 off_t offset, int origin)
111 {
112 return -ESPIPE;
113 }
114
115 static int netlink_open(struct inode * inode, struct file * file)
116 {
117 unsigned int minor = MINOR(inode->i_rdev);
118
119 if(minor>=MAX_LINKS)
120 return -ENODEV;
121 if(open_map&(1<<minor))
122 return -EBUSY;
123 if(active_map&(1<<minor))
124 {
125 open_map|=(1<<minor);
126 return 0;
127 }
128 return -EUNATCH;
129 }
130
131 static void netlink_release(struct inode * inode, struct file * file)
132 {
133 unsigned int minor = MINOR(inode->i_rdev);
134 open_map&=~(1<<minor);
135 MOD_DEC_USE_COUNT;
136 }
137
138
139 static int netlink_ioctl(struct inode *inode, struct file *file,
140 unsigned int cmd, unsigned long arg)
141 {
142 unsigned int minor = MINOR(inode->i_rdev);
143 int retval = 0;
144
145 if (minor >= MAX_LINKS)
146 return -ENODEV;
147 switch ( cmd ) {
148 default:
149 retval = -EINVAL;
150 }
151 return retval;
152 }
153
154
155 static struct file_operations netlink_fops = {
156 netlink_lseek,
157 netlink_read,
158 netlink_write,
159 NULL,
160 NULL,
161 netlink_ioctl,
162 NULL,
163 netlink_open,
164 netlink_release
165 };
166
167
168
169
170
171
172
173 int netlink_attach(int unit, int (*function)(struct sk_buff *skb))
174 {
175 if(unit>=MAX_LINKS)
176 return -ENODEV;
177 if(active_map&(1<<unit))
178 return -EBUSY;
179 active_map|=(1<<unit);
180 netlink_handler[unit]=function;
181 return 0;
182 }
183
184 void netlink_detach(int unit)
185 {
186 active_map&=~(1<<unit);
187 netlink_handler[unit]=netlink_err;
188 }
189
190 int netlink_post(int unit, struct sk_buff *skb)
191 {
192 unsigned long flags;
193 int ret;
194 save_flags(flags);
195 cli();
196 if(rdq_size[unit]+skb->len>MAX_QBYTES)
197 ret=-EWOULDBLOCK;
198 else
199 {
200 skb_queue_tail(&skb_queue_rd[unit], skb);
201 rdq_size[unit]+=skb->len;
202 ret=0;
203 wake_up_interruptible(&read_space_wait[MAX_LINKS]);
204 }
205 restore_flags(flags);
206 return ret;
207 }
208
209
210 #ifdef MODULE
211 char kernel_version[]=UTS_RELEASE;
212
213 int init_module(void)
214 {
215 int ct;
216 printk("Network Kernel/User communications module 0.01 ALPHA\n");
217 if (register_chrdev(NET_MAJOR,"netlink",&netlink_fops)) {
218 printk("netlink: unable to get major %d\n", NET_MAJOR);
219 return -EIO;
220 }
221 for(ct=0;ct<MAX_LINKS;ct++)
222 {
223 skb_queue_head_init(&skb_queue_rd[ct]);
224 netlink_handler[ct]=netlink_err;
225 }
226 return 0;
227 }
228
229 void cleanup_module(void)
230 {
231 unregister_chrdev(NET_MAJOR,"netlink");
232 }
233
234 #else
235
236 void init_netlink(void)
237 {
238 int ct;
239
240 if(register_chrdev(NET_MAJOR,"netlink", &netlink_fops))
241 printk("netlink: unable to get major %d\n", NET_MAJOR);
242 for(ct=0;ct<MAX_LINKS;ct++)
243 {
244 skb_queue_head_init(&skb_queue_rd[ct]);
245 netlink_handler[ct]=netlink_err;
246 }
247 }
248
249 #endif
250 #endif