This source file includes following definitions.
- print_uh
- udp_select
- udp_err
- udp_check
- udp_send_check
- udp_loopback
- udp_sendto
- udp_write
- udp_recvfrom
- udp_read
- udp_connect
- udp_close
- udp_rcv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <linux/types.h>
24 #include <linux/sched.h>
25 #include <linux/fcntl.h>
26 #include <linux/socket.h>
27 #include <netinet/in.h>
28 #include "timer.h"
29 #include "ip.h"
30 #include "tcp.h"
31 #include "sock.h"
32 #include <linux/errno.h>
33 #include <linux/timer.h>
34 #include <asm/system.h>
35 #include <asm/segment.h>
36 #include "../kern_sock.h"
37 #include "udp.h"
38 #include "icmp.h"
39
40 #define min(a,b) ((a)<(b)?(a):(b))
41
42 static void
43 print_uh(struct udp_header *uh)
44 {
45 PRINTK("source = %d, dest = %d\n", net16(uh->source), net16(uh->dest));
46 PRINTK("len = %d, check = %d\n", net16(uh->len), net16(uh->check));
47 }
48
49
50 int
51 udp_select (volatile struct sock *sk, int sel_type, select_table *wait)
52 {
53 select_wait(sk->sleep, wait);
54 switch (sel_type)
55 {
56 case SEL_IN:
57 if (sk->rqueue != NULL)
58 {
59 return (1);
60 }
61 return (0);
62
63 case SEL_OUT:
64 if (sk->prot->wspace(sk) >= MIN_WRITE_SPACE)
65 {
66 return (1);
67 }
68 return (0);
69
70 case SEL_EX:
71 if (sk->err) return (1);
72 return (0);
73 }
74 return (0);
75 }
76
77
78
79
80
81
82
83
84 void
85 udp_err (int err, unsigned char *header, unsigned long daddr,
86 unsigned long saddr, struct ip_protocol *protocol)
87 {
88 struct tcp_header *th;
89 volatile struct sock *sk;
90
91 th = (struct tcp_header *)header;
92 sk = get_sock (&udp_prot, net16(th->dest), saddr, th->source, daddr);
93
94 if (sk == NULL) return;
95 if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8))
96 {
97 if (sk->cong_window > 1)
98 sk->cong_window = sk->cong_window/2;
99 return;
100 }
101
102 sk->err = icmp_err_convert[err & 0xff].errno;
103 if (icmp_err_convert[err & 0xff].fatal)
104 {
105 sk->prot->close(sk, 0);
106 }
107
108 return;
109
110 }
111
112 static unsigned short
113 udp_check (struct udp_header *uh, int len,
114 unsigned long saddr, unsigned long daddr)
115 {
116 unsigned long sum;
117 PRINTK ("udp_check (uh=%X, len = %d, saddr = %X, daddr = %X)\n",
118 uh, len, saddr, daddr);
119
120 print_uh (uh);
121
122 __asm__("\t addl %%ecx,%%ebx\n"
123 "\t adcl %%edx,%%ebx\n"
124 "\t adcl $0, %%ebx\n"
125 : "=b" (sum)
126 : "0" (daddr), "c" (saddr), "d" ((net16(len) << 16) + IP_UDP*256)
127 : "cx","bx","dx" );
128
129 if (len > 3)
130 {
131 __asm__(
132 "\tclc\n"
133 "1:\n"
134 "\t lodsl\n"
135 "\t adcl %%eax, %%ebx\n"
136 "\t loop 1b\n"
137 "\t adcl $0, %%ebx\n"
138 : "=b" (sum) , "=S" (uh)
139 : "0" (sum), "c" (len/4) ,"1" (uh)
140 : "ax", "cx", "bx", "si" );
141 }
142
143
144 __asm__(
145 "\t movl %%ebx, %%ecx\n"
146 "\t shrl $16,%%ecx\n"
147 "\t addw %%cx, %%bx\n"
148 "\t adcw $0, %%bx\n"
149 : "=b" (sum)
150 : "0" (sum)
151 : "bx", "cx");
152
153
154
155 if ((len & 2) != 0)
156 {
157 __asm__("\t lodsw\n"
158 "\t addw %%ax,%%bx\n"
159 "\t adcw $0, %%bx\n"
160 : "=b" (sum), "=S" (uh)
161 : "0" (sum) ,"1" (uh)
162 : "si", "ax", "bx");
163 }
164
165
166 if ((len & 1) != 0)
167 {
168 __asm__("\t lodsb\n"
169 "\t movb $0,%%ah\n"
170 "\t addw %%ax,%%bx\n"
171 "\t adcw $0, %%bx\n"
172 : "=b" (sum)
173 : "0" (sum) ,"S" (uh)
174 : "si", "ax", "bx");
175 }
176
177
178 return ((~sum) & 0xffff);
179 }
180
181 static void
182 udp_send_check (struct udp_header *uh, unsigned long saddr,
183 unsigned long daddr, int len, volatile struct sock *sk)
184 {
185 uh->check = 0;
186 if (sk && sk->no_check) return;
187 uh->check = udp_check (uh, len, saddr, daddr);
188 }
189
190 static int
191 udp_loopback (volatile struct sock *sk, unsigned short port,
192 unsigned char *from,
193 int len, unsigned long daddr, unsigned long saddr)
194 {
195 struct udp_header *uh;
196 struct sk_buff *skb;
197 volatile struct sock *pair;
198 sk->inuse = 1;
199
200 PRINTK ("udp_loopback \n");
201
202 pair = get_sock (sk->prot, net16(port), saddr,
203 sk->dummy_th.source, daddr);
204
205 if (pair == NULL) return (0);
206
207 skb = pair->prot->rmalloc (pair,
208 sizeof (*skb) + sizeof (*uh) + len + 4,
209 0);
210
211
212 if (skb == NULL) return (len);
213
214 skb->mem_addr = skb;
215 skb->mem_len = sizeof (*skb) + len + sizeof (*uh) + 4;
216
217 skb->daddr = saddr;
218 skb->saddr = daddr;
219
220 skb->len = len;
221 skb->h.raw = (unsigned char *)(skb+1);
222
223 uh = skb->h.uh;
224 uh -> source = sk->dummy_th.source;
225 uh -> dest = port;
226 uh -> len = len + sizeof (*uh);
227 verify_area (from , len);
228 memcpy_fromfs(uh+1, from, len);
229 pair->inuse = 1;
230 if (pair->rqueue == NULL)
231 {
232 pair->rqueue = skb;
233 skb->next = skb;
234 skb->prev = skb;
235 }
236 else
237 {
238 skb->next = pair->rqueue;
239 skb->prev = pair->rqueue->prev;
240 skb->prev->next = skb;
241 skb->next->prev = skb;
242 }
243 wake_up (pair->sleep);
244 release_sock (pair);
245 release_sock (sk);
246 return (len);
247
248 }
249
250 static int
251 udp_sendto (volatile struct sock *sk, unsigned char *from, int len,
252 int noblock,
253 unsigned flags, struct sockaddr_in *usin, int addr_len)
254 {
255
256 struct sk_buff *skb;
257 struct udp_header *uh;
258 unsigned char *buff;
259 unsigned long saddr;
260 int copied=0;
261 int amt;
262 struct device *dev=NULL;
263 struct sockaddr_in sin;
264
265
266 if (flags) return (-EINVAL);
267 if (len < 0) return (-EINVAL);
268 if (len == 0) return (0);
269
270 PRINTK ("sendto len = %d\n", len);
271
272
273 if (usin)
274 {
275 if (addr_len < sizeof (sin))
276 return (-EINVAL);
277 verify_area (usin, sizeof (sin));
278 memcpy_fromfs (&sin, usin, sizeof(sin));
279 if (sin.sin_family &&
280 sin.sin_family != AF_INET)
281 return (-EINVAL);
282 if (sin.sin_port == 0)
283 return (-EINVAL);
284 }
285 else
286 {
287 if (sk->state != TCP_ESTABLISHED)
288 return (-EINVAL);
289 sin.sin_family = AF_INET;
290 sin.sin_port = sk->dummy_th.dest;
291 sin.sin_addr.s_addr = sk->daddr;
292 }
293
294
295 saddr = sk->saddr;
296 if ((saddr & 0xff000000) == 0)
297 {
298 saddr = MY_IP_ADDR;
299 }
300
301
302 if ((sin.sin_addr.s_addr & 0xff000000) == 0)
303 {
304 int err;
305 err = udp_loopback (sk, sin.sin_port, from, len,
306 sin.sin_addr.s_addr, saddr);
307 if (err < 0)
308 return (err);
309 }
310
311 sk->inuse = 1;
312
313 while (len > 0)
314 {
315 int tmp;
316 skb = sk->prot->wmalloc (sk, len + sizeof (*skb)
317 + sk->prot->max_header, 0);
318
319
320 if (skb == NULL)
321 {
322 printk ("udp_sendto: write buffer full?\n");
323 print_sk(sk);
324 release_sock (sk);
325 if (copied || !noblock)
326 return (copied);
327 return (-EAGAIN);
328 }
329
330 skb->mem_addr = skb;
331 skb->mem_len = len + sizeof (*skb) + sk->prot->max_header;
332 skb->sk = sk;
333 skb->free = 1;
334 skb->arp = 0;
335
336
337 buff = (unsigned char *)(skb+1);
338 tmp = sk->prot->build_header (skb, saddr,
339 sin.sin_addr.s_addr, &dev,
340 IP_UDP, sk->opt, skb->mem_len);
341 if (tmp < 0 )
342 {
343 sk->prot->wfree (sk, skb->mem_addr, skb->mem_len);
344 release_sock (sk);
345 return (tmp);
346 }
347 buff += tmp;
348
349
350
351 amt = min (len + tmp + sizeof (*uh), dev->mtu);
352
353 PRINTK ("amt = %d, dev = %X, dev->mtu = %d\n",
354 amt, dev, dev->mtu);
355
356 skb->len = amt;
357 amt -= tmp;
358
359 uh = (struct udp_header *)buff;
360 uh->len = net16(amt);
361 uh->source = sk->dummy_th.source;
362 uh->dest = sin.sin_port;
363
364 amt -= sizeof (*uh);
365 buff += sizeof (*uh);
366
367 verify_area (from, amt);
368 memcpy_fromfs( buff, from, amt);
369
370 len -= amt;
371 copied += amt;
372 from += amt;
373 udp_send_check (uh, saddr, sin.sin_addr.s_addr,
374 amt+sizeof (*uh), sk);
375
376 sk->prot->queue_xmit (sk, dev, skb, 1);
377 }
378 release_sock (sk);
379 return (copied);
380 }
381
382 static int
383 udp_write (volatile struct sock *sk, unsigned char *buff, int len, int noblock,
384 unsigned flags)
385 {
386 return (udp_sendto (sk, buff, len, noblock, flags, NULL, 0));
387 }
388
389 int
390 udp_recvfrom (volatile struct sock *sk, unsigned char *to, int len,
391 int noblock,
392 unsigned flags, struct sockaddr_in *sin, int *addr_len)
393 {
394
395
396 int copied=0;
397 struct sk_buff *skb;
398 if (len == 0) return (0);
399 if (len < 0) return (-EINVAL);
400 if (addr_len)
401 {
402 verify_area (addr_len, sizeof(*addr_len));
403 put_fs_long (sizeof (*sin), addr_len);
404 }
405 sk->inuse = 1;
406 while (sk->rqueue == NULL)
407 {
408 if (noblock)
409 {
410 release_sock (sk);
411 return (-EAGAIN);
412 }
413 release_sock (sk);
414 cli();
415 if (sk->rqueue == NULL)
416 {
417 interruptible_sleep_on (sk->sleep);
418 if (current->signal & ~current->blocked)
419 {
420 return (-ERESTARTSYS);
421 }
422 }
423 sti();
424 }
425 skb = sk->rqueue;
426
427 if (!(flags & MSG_PEEK))
428 {
429 if (skb->next == skb )
430 {
431 sk->rqueue = NULL;
432 }
433 else
434 {
435 sk->rqueue = sk->rqueue ->next;
436 skb->prev->next = skb->next;
437 skb->next->prev = skb->prev;
438 }
439 }
440 copied = min (len, skb->len);
441 verify_area (to, copied);
442 memcpy_tofs (to, skb->h.raw + sizeof (struct udp_header), copied);
443
444 if (sin)
445 {
446 struct sockaddr_in addr;
447 addr.sin_family = AF_INET;
448 addr.sin_port = skb->h.uh->source;
449 addr.sin_addr.s_addr = skb->daddr;
450 verify_area (sin, sizeof (*sin));
451 memcpy_tofs(sin, &addr, sizeof (*sin));
452 }
453
454 if (!(flags & MSG_PEEK))
455 {
456 free_skb (skb, FREE_READ);
457 }
458 release_sock (sk);
459 return (copied);
460
461 }
462
463
464 int
465 udp_read (volatile struct sock *sk, unsigned char *buff, int len, int noblock,
466 unsigned flags)
467 {
468 return (udp_recvfrom (sk, buff, len, noblock, flags, NULL, NULL));
469 }
470
471 int
472 udp_connect (volatile struct sock *sk, struct sockaddr_in *usin, int addr_len)
473 {
474 struct sockaddr_in sin;
475 if (addr_len < sizeof (sin)) return (-EINVAL);
476 verify_area (usin, sizeof (sin));
477 memcpy_fromfs (&sin, usin, sizeof (sin));
478 if (sin.sin_family && sin.sin_family != AF_INET)
479 return (-EAFNOSUPPORT);
480 sk->daddr = sin.sin_addr.s_addr;
481 sk->dummy_th.dest = sin.sin_port;
482 sk->state = TCP_ESTABLISHED;
483 return(0);
484 }
485
486 static void
487 udp_close(volatile struct sock *sk, int timeout)
488 {
489 sk->inuse = 1;
490 sk->state = TCP_CLOSE;
491 if (sk->dead)
492 destroy_sock (sk);
493 else
494 release_sock (sk);
495 }
496
497 int
498 udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
499 unsigned long daddr, unsigned short len,
500 unsigned long saddr, int redo, struct ip_protocol *protocol)
501 {
502
503 struct proto *prot=&udp_prot;
504 volatile struct sock *sk;
505 struct udp_header *uh;
506
507 uh = (struct udp_header *) skb->h.uh;
508
509 if (dev->add_arp) dev->add_arp (saddr, skb, dev);
510
511 sk = get_sock (prot, net16(uh->dest), saddr, uh->source, daddr);
512
513
514 if (sk == NULL &&
515 (daddr & 0xff000000 != 0) && (daddr & 0xff000000 != 0xff000000))
516 {
517 icmp_reply (skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
518 skb->sk = NULL;
519 free_skb (skb, 0);
520 return (0);
521 }
522
523
524 if (!redo)
525 {
526 if (uh->check && udp_check (uh, len, saddr, daddr))
527 {
528 PRINTK ("bad udp checksum\n");
529 skb->sk = NULL;
530 free_skb (skb, 0);
531 return (0);
532 }
533
534 skb->sk = sk;
535 skb->dev = dev;
536 skb->len = len;
537
538
539 skb->daddr = saddr;
540 skb->saddr = daddr;
541
542
543 cli();
544 if (sk->inuse)
545 {
546 if (sk->back_log == NULL)
547 {
548 sk->back_log = skb;
549 skb->next = skb;
550 skb->prev = skb;
551 }
552 else
553 {
554 skb->next = sk->back_log;
555 skb->prev = sk->back_log->prev;
556 skb->prev->next = skb;
557 skb->next->prev = skb;
558 }
559 sti();
560 return (0);
561 }
562 sk->inuse = 1;
563 sti();
564 }
565
566
567 if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX)
568 {
569 skb->sk = NULL;
570 free_skb (skb, 0);
571 release_sock (sk);
572 return (0);
573 }
574
575 sk->rmem_alloc += skb->mem_len;
576
577
578 PRINTK ("<< \n");
579 print_sk (sk);
580
581
582 if (sk->rqueue == NULL)
583 {
584 sk->rqueue = skb;
585 skb->next = skb;
586 skb->prev = skb;
587 }
588 else
589 {
590 skb->next = sk->rqueue;
591 skb->prev = sk->rqueue->prev;
592 skb->prev->next = skb;
593 skb->next->prev = skb;
594 }
595
596 skb->len = len - sizeof (*uh);
597
598 if (!sk->dead)
599 wake_up (sk->sleep);
600
601 release_sock (sk);
602 return (0);
603 }
604
605
606
607 struct proto udp_prot =
608 {
609 sock_wmalloc,
610 sock_rmalloc,
611 sock_wfree,
612 sock_rfree,
613 sock_rspace,
614 sock_wspace,
615 udp_close,
616 udp_read,
617 udp_write,
618 udp_sendto,
619 udp_recvfrom,
620 ip_build_header,
621 udp_connect,
622 NULL,
623 ip_queue_xmit,
624 ip_retransmit,
625 NULL,
626 NULL,
627 udp_rcv,
628 udp_select,
629 NULL,
630 NULL,
631 128,
632 0,
633 {NULL,}
634 };
635