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