This source file includes following definitions.
- min
- raw_err
- raw_rcv
- raw_getfrag
- raw_getrawfrag
- raw_sendto
- raw_write
- raw_close
- raw_init
- raw_recvfrom
- raw_read
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
28
29
30
31
32
33
34
35
36
37
38 #include <asm/system.h>
39 #include <asm/segment.h>
40 #include <linux/types.h>
41 #include <linux/sched.h>
42 #include <linux/errno.h>
43 #include <linux/timer.h>
44 #include <linux/mm.h>
45 #include <linux/kernel.h>
46 #include <linux/fcntl.h>
47 #include <linux/socket.h>
48 #include <linux/in.h>
49 #include <linux/inet.h>
50 #include <linux/netdevice.h>
51 #include <linux/mroute.h>
52 #include <net/ip.h>
53 #include <net/protocol.h>
54 #include <linux/skbuff.h>
55 #include <net/sock.h>
56 #include <net/icmp.h>
57 #include <net/udp.h>
58 #include <net/checksum.h>
59
60 #ifdef CONFIG_IP_MROUTE
61 struct sock *mroute_socket=NULL;
62 #endif
63
64 static inline unsigned long min(unsigned long a, unsigned long b)
65 {
66 if (a < b)
67 return(a);
68 return(b);
69 }
70
71
72
73
74
75
76 void raw_err (int type, int code, unsigned char *header, __u32 daddr,
77 __u32 saddr, struct inet_protocol *protocol)
78 {
79 struct sock *sk;
80
81 if (protocol == NULL)
82 return;
83 sk = (struct sock *) protocol->data;
84 if (sk == NULL)
85 return;
86
87
88 if (type == ICMP_SOURCE_QUENCH)
89 {
90 if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
91 return;
92 }
93
94 if(type == ICMP_PARAMETERPROB)
95 {
96 sk->err = EPROTO;
97 sk->error_report(sk);
98 }
99
100 if(code<13)
101 {
102 sk->err = icmp_err_convert[code & 0xff].errno;
103 sk->error_report(sk);
104 }
105
106 return;
107 }
108
109
110
111
112
113
114
115
116 int raw_rcv(struct sock *sk, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr)
117 {
118
119 skb->sk = sk;
120 skb_trim(skb,ntohs(skb->ip_hdr->tot_len));
121
122 skb->h.raw = (unsigned char *) skb->ip_hdr;
123 skb->dev = dev;
124 skb->saddr = daddr;
125 skb->daddr = saddr;
126
127
128
129 if(sock_queue_rcv_skb(sk,skb)<0)
130 {
131 ip_statistics.IpInDiscards++;
132 skb->sk=NULL;
133 kfree_skb(skb, FREE_READ);
134 return(0);
135 }
136
137 ip_statistics.IpInDelivers++;
138 release_sock(sk);
139 return(0);
140 }
141
142
143
144
145
146
147
148
149
150 static void raw_getfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
151 {
152 memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
153 }
154
155
156
157
158
159 static void raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
160 {
161 memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
162 if(offset==0)
163 {
164 struct iphdr *iph=(struct iphdr *)to;
165 iph->saddr=saddr;
166 iph->check=0;
167 iph->tot_len=htons(fraglen);
168
169
170
171
172
173 iph->id = htons(ip_id_count++);
174 iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
175 }
176 }
177
178 static int raw_sendto(struct sock *sk, const unsigned char *from,
179 int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len)
180 {
181 int err;
182 struct sockaddr_in sin;
183
184
185
186
187
188 if (flags & MSG_OOB)
189 return -EOPNOTSUPP;
190
191 if (flags & ~MSG_DONTROUTE)
192 return(-EINVAL);
193
194
195
196
197 if (usin)
198 {
199 if (addr_len < sizeof(sin))
200 return(-EINVAL);
201 memcpy(&sin, usin, sizeof(sin));
202 if (sin.sin_family && sin.sin_family != AF_INET)
203 return(-EINVAL);
204 }
205 else
206 {
207 if (sk->state != TCP_ESTABLISHED)
208 return(-EINVAL);
209 sin.sin_family = AF_INET;
210 sin.sin_port = sk->protocol;
211 sin.sin_addr.s_addr = sk->daddr;
212 }
213 if (sin.sin_port == 0)
214 sin.sin_port = sk->protocol;
215
216 if (sin.sin_addr.s_addr == INADDR_ANY)
217 sin.sin_addr.s_addr = ip_my_addr();
218
219 if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
220 return -EACCES;
221
222 if(sk->ip_hdrincl)
223 err=ip_build_xmit(sk, raw_getrawfrag, from, len, sin.sin_addr.s_addr, flags, sin.sin_port);
224 else
225 err=ip_build_xmit(sk, raw_getfrag, from, len, sin.sin_addr.s_addr, flags, sin.sin_port);
226 return err<0?err:len;
227 }
228
229
230 static int raw_write(struct sock *sk, const unsigned char *buff, int len, int noblock,
231 unsigned flags)
232 {
233 return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
234 }
235
236
237 static void raw_close(struct sock *sk, int timeout)
238 {
239 sk->state = TCP_CLOSE;
240 #ifdef CONFIG_IP_MROUTE
241 if(sk==mroute_socket)
242 {
243 mroute_close(sk);
244 mroute_socket=NULL;
245 }
246 #endif
247 }
248
249
250 static int raw_init(struct sock *sk)
251 {
252 return(0);
253 }
254
255
256
257
258
259
260
261 int raw_recvfrom(struct sock *sk, unsigned char *to, int len,
262 int noblock, unsigned flags, struct sockaddr_in *sin,
263 int *addr_len)
264 {
265 int copied=0;
266 struct sk_buff *skb;
267 int err;
268
269 if (flags & MSG_OOB)
270 return -EOPNOTSUPP;
271
272 if (sk->shutdown & RCV_SHUTDOWN)
273 return(0);
274
275 if (addr_len)
276 *addr_len=sizeof(*sin);
277
278 skb=skb_recv_datagram(sk,flags,noblock,&err);
279 if(skb==NULL)
280 return err;
281
282 copied = min(len, skb->len);
283
284 skb_copy_datagram(skb, 0, to, copied);
285 sk->stamp=skb->stamp;
286
287
288 if (sin)
289 {
290 sin->sin_family = AF_INET;
291 sin->sin_addr.s_addr = skb->daddr;
292 }
293 skb_free_datagram(skb);
294 release_sock(sk);
295 return (copied);
296 }
297
298
299 int raw_read (struct sock *sk, unsigned char *buff, int len, int noblock,unsigned flags)
300 {
301 return(raw_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
302 }
303
304
305 struct proto raw_prot = {
306 sock_wmalloc,
307 sock_rmalloc,
308 sock_wfree,
309 sock_rfree,
310 sock_rspace,
311 sock_wspace,
312 raw_close,
313 raw_read,
314 raw_write,
315 raw_sendto,
316 raw_recvfrom,
317 ip_build_header,
318 udp_connect,
319 NULL,
320 ip_queue_xmit,
321 NULL,
322 NULL,
323 NULL,
324 NULL,
325 datagram_select,
326 #ifdef CONFIG_IP_MROUTE
327 ipmr_ioctl,
328 #else
329 NULL,
330 #endif
331 raw_init,
332 NULL,
333 ip_setsockopt,
334 ip_getsockopt,
335 128,
336 0,
337 "RAW",
338 0, 0,
339 {NULL,}
340 };