This source file includes following definitions.
- ip_mroute_setsockopt
- ip_mroute_getsockopt
- ipmr_ioctl
- mroute_close
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <asm/system.h>
14 #include <asm/segment.h>
15 #include <linux/types.h>
16 #include <linux/sched.h>
17 #include <linux/errno.h>
18 #include <linux/timer.h>
19 #include <linux/mm.h>
20 #include <linux/kernel.h>
21 #include <linux/fcntl.h>
22 #include <linux/socket.h>
23 #include <linux/in.h>
24 #include <linux/inet.h>
25 #include <linux/netdevice.h>
26 #include <linux/mroute.h>
27 #include <net/ip.h>
28 #include <net/protocol.h>
29 #include <linux/skbuff.h>
30 #include <net/sock.h>
31 #include <net/icmp.h>
32 #include <net/udp.h>
33 #include <net/checksum.h>
34
35 #ifdef CONFIG_IP_MROUTE
36
37
38
39
40
41 static struct vif_device vif_table[MAXVIFS];
42 static unsigned long vifc_map;
43 int mroute_do_pim = 0;
44
45
46
47
48
49
50
51
52 int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
53 {
54 int err;
55 struct vifctl vif;
56
57 if(optname!=MRT_INIT)
58 {
59 if(sk!=mroute_socket)
60 return -EACCES;
61 }
62
63 switch(optname)
64 {
65 case MRT_INIT:
66 if(sk->type!=SOCK_RAW || sk->num!=IPPROTO_IGMP)
67 return -EOPNOTSUPP;
68 if(optlen!=sizeof(int))
69 return -ENOPROTOOPT;
70 if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
71 return err;
72 if(get_user((int *)optval)!=1)
73 return -ENOPROTOOPT;
74 if(mroute_socket)
75 return -EADDRINUSE;
76 mroute_socket=sk;
77
78 return 0;
79 case MRT_DONE:
80 mroute_close(sk);
81 mroute_socket=NULL;
82 return 0;
83 case MRT_ADD_VIF:
84 case MRT_DEL_VIF:
85 if(optlen!=sizeof(vif))
86 return -EINVAL;
87 if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
88 return err;
89 memcpy_fromfs(&vif,optval,sizeof(vif));
90 if(vif.vifc_vifi > MAXVIFS)
91 return -ENFILE;
92 if(optname==MRT_ADD_VIF)
93 {
94 struct vif_device *v=&vif_table[vif.vifc_vifi];
95 struct device *dev;
96
97 if(vifc_map&(1<<vif.vifc_vifi))
98 return -EADDRINUSE;
99
100 dev=ip_dev_find(vif.vifc_lcl_addr.s_addr);
101 if(!dev)
102 return -EADDRNOTAVAIL;
103
104 if(vif.vifc_flags&VIFF_TUNNEL)
105 {
106 if(vif.vifc_flags&VIFF_SRCRT)
107 return -EOPNOTSUPP;
108
109 }
110 else
111 {
112 if(dev->flags&IFF_MULTICAST)
113 {
114
115
116 dev->flags|=IFF_ALLMULTI;
117 dev_mc_upload(dev);
118 }
119 else
120 {
121
122 return -EOPNOTSUPP;
123 }
124 }
125
126
127
128 cli();
129 v->rate_limit=vif.vifc_rate_limit;
130 v->local=vif.vifc_lcl_addr.s_addr;
131 v->remote=vif.vifc_rmt_addr.s_addr;
132 v->flags=vif.vifc_flags;
133 v->threshold=vif.vifc_threshold;
134 v->dev=dev;
135 v->bytes_in = 0;
136 v->bytes_out = 0;
137 v->pkt_in = 0;
138 v->pkt_out = 0;
139 vifc_map|=(1<<vif.vifc_vifi);
140 sti();
141 return 0;
142 }
143 else
144
145
146
147 {
148 struct vif_device *v=&vif_table[vif.vifc_vifi];
149 if(vifc_map&(1<<vif.vifc_vifi))
150 {
151 if(!(v->flags&VIFF_TUNNEL))
152 {
153 v->dev->flags&=~IFF_ALLMULTI;
154 dev_mc_upload(v->dev);
155 }
156 vifc_map&=~(1<<vif.vifc_vifi);
157 return 0;
158 }
159 else
160 return -EADDRNOTAVAIL;
161 }
162
163
164
165
166 case MRT_ADD_MFC:
167 case MRT_DEL_MFC:
168 return -EOPNOTSUPP;
169
170
171
172 case MRT_ASSERT:
173 if(optlen!=sizeof(int))
174 return -EINVAL;
175 if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
176 return err;
177 mroute_do_pim= (optval)?1:0;
178 return 0;
179
180
181
182
183 default:
184 return -EOPNOTSUPP;
185 }
186 }
187
188
189
190
191
192 int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
193 {
194 int olr;
195 int err;
196
197 if(sk!=mroute_socket)
198 return -EACCES;
199 if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
200 return -EOPNOTSUPP;
201
202 olr=get_user(optlen);
203 if(olr!=sizeof(int))
204 return -EINVAL;
205 err=verify_area(VERIFY_WRITE, optval,sizeof(int));
206 if(err)
207 return err;
208 put_user(sizeof(int),optlen);
209 if(optname==MRT_VERSION)
210 put_user(0x0305,(int *)optval);
211 else
212 put_user(mroute_do_pim,(int *)optval);
213 return 0;
214 }
215
216
217
218
219
220 int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
221 {
222 int err;
223 struct sioc_sg_req sr;
224 struct sioc_vif_req vr;
225 struct vif_device *vif;
226
227 switch(cmd)
228 {
229 case SIOCGETVIFCNT:
230 err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
231 if(err)
232 return err;
233 memcpy_fromfs(&vr,(void *)arg,sizeof(sr));
234 if(vr.vifi>=MAXVIFS)
235 return -EINVAL;
236 vif=&vif_table[vr.vifi];
237 if(vifc_map&(1<<vr.vifi))
238 {
239 vr.icount=vif->pkt_in;
240 vr.ocount=vif->pkt_out;
241 vr.ibytes=vif->bytes_in;
242 vr.obytes=vif->bytes_out;
243 memcpy_tofs((void *)arg,&vr,sizeof(sr));
244 return 0;
245 }
246 return -EADDRNOTAVAIL;
247 case SIOCGETSGCNT:
248 err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
249 if(err)
250 return err;
251 memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
252 memcpy_tofs((void *)arg,&sr,sizeof(sr));
253 return 0;
254 default:
255 return -EINVAL;
256 }
257 }
258
259
260
261
262
263 void mroute_close(struct sock *sk)
264 {
265 int i;
266 struct vif_device *v=&vif_table[0];
267
268
269
270
271
272 for(i=0;i<MAXVIFS;i++)
273 {
274 if(vifc_map&(1<<i))
275 {
276 if(!(v->flags&VIFF_TUNNEL))
277 {
278 v->dev->flags&=~IFF_ALLMULTI;
279 dev_mc_upload(v->dev);
280 }
281 }
282 v++;
283 }
284 vifc_map=0;
285 }
286
287 #endif