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