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