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