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