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