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 memcpy_fromfs(skb_put(skb,count),buf, count);
76 return (netlink_handler[minor])(skb);
77 }
78
79
80
81
82
83 static int netlink_read(struct inode * inode, struct file * file, char * buf, int count)
84 {
85 unsigned int minor = MINOR(inode->i_rdev);
86 struct sk_buff *skb;
87 cli();
88 while((skb=skb_dequeue(&skb_queue_rd[minor]))==NULL)
89 {
90 if(file->f_flags&O_NONBLOCK)
91 {
92 sti();
93 return -EWOULDBLOCK;
94 }
95 interruptible_sleep_on(&read_space_wait[minor]);
96 if(current->signal & ~current->blocked)
97 {
98 sti();
99 return -ERESTARTSYS;
100 }
101 }
102 rdq_size[minor]-=skb->len;
103 sti();
104 if(skb->len<count)
105 count=skb->len;
106 memcpy_tofs(buf,skb->data,count);
107 kfree_skb(skb, FREE_READ);
108 return count;
109 }
110
111 static int netlink_lseek(struct inode * inode, struct file * file,
112 off_t offset, int origin)
113 {
114 return -ESPIPE;
115 }
116
117 static int netlink_open(struct inode * inode, struct file * file)
118 {
119 unsigned int minor = MINOR(inode->i_rdev);
120
121 if(minor>=MAX_LINKS)
122 return -ENODEV;
123 if(open_map&(1<<minor))
124 return -EBUSY;
125 if(active_map&(1<<minor))
126 {
127 open_map|=(1<<minor);
128 MOD_INC_USE_COUNT;
129 return 0;
130 }
131 return -EUNATCH;
132 }
133
134 static void netlink_release(struct inode * inode, struct file * file)
135 {
136 unsigned int minor = MINOR(inode->i_rdev);
137 open_map&=~(1<<minor);
138 MOD_DEC_USE_COUNT;
139 }
140
141
142 static int netlink_ioctl(struct inode *inode, struct file *file,
143 unsigned int cmd, unsigned long arg)
144 {
145 unsigned int minor = MINOR(inode->i_rdev);
146 int retval = 0;
147
148 if (minor >= MAX_LINKS)
149 return -ENODEV;
150 switch ( cmd ) {
151 default:
152 retval = -EINVAL;
153 }
154 return retval;
155 }
156
157
158 static struct file_operations netlink_fops = {
159 netlink_lseek,
160 netlink_read,
161 netlink_write,
162 NULL,
163 NULL,
164 netlink_ioctl,
165 NULL,
166 netlink_open,
167 netlink_release
168 };
169
170
171
172
173
174
175
176 int netlink_attach(int unit, int (*function)(struct sk_buff *skb))
177 {
178 if(unit>=MAX_LINKS)
179 return -ENODEV;
180 if(active_map&(1<<unit))
181 return -EBUSY;
182 active_map|=(1<<unit);
183 netlink_handler[unit]=function;
184 return 0;
185 }
186
187 void netlink_detach(int unit)
188 {
189 active_map&=~(1<<unit);
190 netlink_handler[unit]=netlink_err;
191 }
192
193 int netlink_post(int unit, struct sk_buff *skb)
194 {
195 unsigned long flags;
196 int ret=0;
197 if(open_map&(1<<unit))
198 {
199 save_flags(flags);
200 cli();
201 if(rdq_size[unit]+skb->len>MAX_QBYTES)
202 ret=-EWOULDBLOCK;
203 else
204 {
205 skb_queue_tail(&skb_queue_rd[unit], skb);
206 rdq_size[unit]+=skb->len;
207 ret=0;
208 wake_up_interruptible(&read_space_wait[unit]);
209 }
210 restore_flags(flags);
211 }
212 return ret;
213 }
214
215 int init_netlink(void)
216 {
217 int ct;
218
219 if(register_chrdev(NETLINK_MAJOR,"netlink", &netlink_fops)) {
220 printk("netlink: unable to get major %d\n", NETLINK_MAJOR);
221 return -EIO;
222 }
223 for(ct=0;ct<MAX_LINKS;ct++)
224 {
225 skb_queue_head_init(&skb_queue_rd[ct]);
226 netlink_handler[ct]=netlink_err;
227 }
228 return 0;
229 }
230
231 #ifdef MODULE
232
233 int init_module(void)
234 {
235 printk("Network Kernel/User communications module 0.03\n");
236 return init_netlink();
237 }
238
239 void cleanup_module(void)
240 {
241 unregister_chrdev(NET_MAJOR,"netlink");
242 }
243
244 #endif