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