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