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)
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
285
286
287
288
289 buff = skb->data;
290 saddr = 0;
291 dev = NULL;
292 DPRINTF((DBG_UDP, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n",
293 saddr, sin->sin_addr.s_addr, dev, IPPROTO_UDP, skb->mem_len));
294 tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
295 &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
296 skb->sk=sk;
297
298
299
300
301
302 if (tmp < 0 )
303 {
304 sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
305 return(tmp);
306 }
307
308 buff += tmp;
309 saddr = skb->saddr;
310 DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp));
311
312 skb->len = tmp + sizeof(struct udphdr) + len;
313 skb->dev = dev;
314
315
316
317
318
319 uh = (struct udphdr *) buff;
320 uh->len = htons(len + sizeof(struct udphdr));
321 uh->source = sk->dummy_th.source;
322 uh->dest = sin->sin_port;
323 buff = (unsigned char *) (uh + 1);
324
325
326
327
328
329 memcpy_fromfs(buff, from, len);
330
331
332
333
334
335 udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
336
337
338
339
340
341 udp_statistics.UdpOutDatagrams++;
342
343 sk->prot->queue_xmit(sk, dev, skb, 1);
344 return(len);
345 }
346
347
348 static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
349 unsigned flags, struct sockaddr_in *usin, int addr_len)
350 {
351 struct sockaddr_in sin;
352 int tmp;
353 int err;
354
355 DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
356
357
358
359
360 if (flags)
361 return(-EINVAL);
362 if (len < 0)
363 return(-EINVAL);
364 if (len == 0)
365 return(0);
366
367
368
369
370
371 if (usin)
372 {
373 if (addr_len < sizeof(sin))
374 return(-EINVAL);
375 err=verify_area(VERIFY_READ, usin, sizeof(sin));
376 if(err)
377 return err;
378 memcpy_fromfs(&sin, usin, sizeof(sin));
379 if (sin.sin_family && sin.sin_family != AF_INET)
380 return(-EINVAL);
381 if (sin.sin_port == 0)
382 return(-EINVAL);
383 }
384 else
385 {
386 if (sk->state != TCP_ESTABLISHED)
387 return(-EINVAL);
388 sin.sin_family = AF_INET;
389 sin.sin_port = sk->dummy_th.dest;
390 sin.sin_addr.s_addr = sk->daddr;
391 }
392
393
394
395
396
397 if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
398 return -EACCES;
399
400 sk->inuse = 1;
401
402
403 tmp = udp_send(sk, &sin, from, len);
404
405
406 release_sock(sk);
407 return(tmp);
408 }
409
410
411
412
413
414 static int udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
415 unsigned flags)
416 {
417 return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
418 }
419
420
421
422
423
424
425 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
426 {
427 int err;
428 switch(cmd)
429 {
430 case DDIOCSDBG:
431 {
432 int val;
433
434 if (!suser()) return(-EPERM);
435 err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
436 if(err)
437 return err;
438 val = get_fs_long((int *)arg);
439 switch(val) {
440 case 0:
441 inet_debug = 0;
442 break;
443 case 1:
444 inet_debug = DBG_UDP;
445 break;
446 default:
447 return(-EINVAL);
448 }
449 }
450 break;
451 case TIOCOUTQ:
452 {
453 unsigned long amount;
454
455 if (sk->state == TCP_LISTEN) return(-EINVAL);
456 amount = sk->prot->wspace(sk);
457 err=verify_area(VERIFY_WRITE,(void *)arg,
458 sizeof(unsigned long));
459 if(err)
460 return(err);
461 put_fs_long(amount,(unsigned long *)arg);
462 return(0);
463 }
464
465 case TIOCINQ:
466 {
467 struct sk_buff *skb;
468 unsigned long amount;
469
470 if (sk->state == TCP_LISTEN) return(-EINVAL);
471 amount = 0;
472 skb = skb_peek(&sk->receive_queue);
473 if (skb != NULL) {
474
475
476
477
478
479 amount = skb->len;
480 }
481 err=verify_area(VERIFY_WRITE,(void *)arg,
482 sizeof(unsigned long));
483 if(err)
484 return(err);
485 put_fs_long(amount,(unsigned long *)arg);
486 return(0);
487 }
488
489 default:
490 return(-EINVAL);
491 }
492 return(0);
493 }
494
495
496
497
498
499
500
501 int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
502 int noblock, unsigned flags, struct sockaddr_in *sin,
503 int *addr_len)
504 {
505 int copied = 0;
506 struct sk_buff *skb;
507 int er;
508
509
510
511
512
513
514
515 if (sk->err)
516 {
517 int err;
518
519 err = -sk->err;
520 sk->err = 0;
521 return(err);
522 }
523
524 if (len == 0)
525 return(0);
526 if (len < 0)
527 return(-EINVAL);
528
529
530
531
532
533 if (addr_len)
534 {
535 er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
536 if(er)
537 return(er);
538 put_fs_long(sizeof(*sin), addr_len);
539 }
540
541 if(sin)
542 {
543 er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
544 if(er)
545 return(er);
546 }
547
548
549
550
551
552 er=verify_area(VERIFY_WRITE,to,len);
553 if(er)
554 return er;
555
556
557
558
559
560
561 skb=skb_recv_datagram(sk,flags,noblock,&er);
562 if(skb==NULL)
563 return er;
564
565 copied = min(len, skb->len);
566
567
568
569
570
571 skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
572 sk->stamp=skb->stamp;
573
574
575 if (sin)
576 {
577 struct sockaddr_in addr;
578
579 addr.sin_family = AF_INET;
580 addr.sin_port = skb->h.uh->source;
581 addr.sin_addr.s_addr = skb->daddr;
582 memcpy_tofs(sin, &addr, sizeof(*sin));
583 }
584
585 skb_free_datagram(skb);
586 release_sock(sk);
587 return(copied);
588 }
589
590
591
592
593
594 int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
595 unsigned flags)
596 {
597 return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
598 }
599
600
601 int
602 udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
603 {
604 struct sockaddr_in sin;
605 int er;
606
607 if (addr_len < sizeof(sin))
608 return(-EINVAL);
609
610 er=verify_area(VERIFY_READ, usin, sizeof(sin));
611 if(er)
612 return er;
613
614 memcpy_fromfs(&sin, usin, sizeof(sin));
615 if (sin.sin_family && sin.sin_family != AF_INET)
616 return(-EAFNOSUPPORT);
617
618 if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
619 return -EACCES;
620
621 sk->daddr = sin.sin_addr.s_addr;
622 sk->dummy_th.dest = sin.sin_port;
623 sk->state = TCP_ESTABLISHED;
624 return(0);
625 }
626
627
628 static void
629 udp_close(struct sock *sk, int timeout)
630 {
631 sk->inuse = 1;
632 sk->state = TCP_CLOSE;
633 if (sk->dead) destroy_sock(sk);
634 else release_sock(sk);
635 }
636
637
638
639
640
641
642 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
643 unsigned long daddr, unsigned short len,
644 unsigned long saddr, int redo, struct inet_protocol *protocol)
645 {
646 struct sock *sk;
647 struct udphdr *uh;
648
649
650
651
652 uh = (struct udphdr *) skb->h.uh;
653
654 ip_statistics.IpInDelivers++;
655
656
657 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
658 if (sk == NULL)
659 {
660 udp_statistics.UdpNoPorts++;
661 if (ip_chk_addr(daddr) == IS_MYADDR)
662 {
663 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
664 }
665
666
667
668
669 skb->sk = NULL;
670 kfree_skb(skb, FREE_WRITE);
671 return(0);
672 }
673
674 if (uh->check && udp_check(uh, len, saddr, daddr))
675 {
676 printk("UDP: bad checksum.\n");
677 DPRINTF((DBG_UDP, "UDP: bad checksum\n"));
678 udp_statistics.UdpInErrors++;
679 kfree_skb(skb, FREE_WRITE);
680 return(0);
681 }
682
683 skb->sk = sk;
684 skb->dev = dev;
685 skb->len = len;
686
687
688
689
690
691 skb->daddr = saddr;
692 skb->saddr = daddr;
693
694
695
696
697
698
699 if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
700 {
701 udp_statistics.UdpInErrors++;
702 ip_statistics.IpInDiscards++;
703 ip_statistics.IpInDelivers--;
704 skb->sk = NULL;
705 kfree_skb(skb, FREE_WRITE);
706 release_sock(sk);
707 return(0);
708 }
709 sk->rmem_alloc += skb->mem_len;
710 udp_statistics.UdpInDatagrams++;
711
712
713
714
715
716 DPRINTF((DBG_UDP, "<< \n"));
717 print_udp(uh);
718
719
720
721
722
723 skb->len = len - sizeof(*uh);
724 skb_queue_tail(&sk->receive_queue,skb);
725
726
727 if (!sk->dead)
728 sk->data_ready(sk,skb->len);
729
730 release_sock(sk);
731 return(0);
732 }
733
734
735 struct proto udp_prot = {
736 sock_wmalloc,
737 sock_rmalloc,
738 sock_wfree,
739 sock_rfree,
740 sock_rspace,
741 sock_wspace,
742 udp_close,
743 udp_read,
744 udp_write,
745 udp_sendto,
746 udp_recvfrom,
747 ip_build_header,
748 udp_connect,
749 NULL,
750 ip_queue_xmit,
751 ip_retransmit,
752 NULL,
753 NULL,
754 udp_rcv,
755 datagram_select,
756 udp_ioctl,
757 NULL,
758 NULL,
759 ip_setsockopt,
760 ip_getsockopt,
761 128,
762 0,
763 {NULL,},
764 "UDP"
765 };