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