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_recvmsg
- 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 type, int code, unsigned char *header, __u32 daddr,
154 __u32 saddr, struct inet_protocol *protocol)
155 {
156 struct udphdr *uh;
157 struct sock *sk;
158
159
160
161
162
163 uh = (struct udphdr *)header;
164
165 sk = get_sock(&udp_prot, uh->source, daddr, uh->dest, saddr);
166
167 if (sk == NULL)
168 return;
169
170 if (type == ICMP_SOURCE_QUENCH)
171 {
172 if (sk->cong_window > 1)
173 sk->cong_window = sk->cong_window/2;
174 return;
175 }
176
177 if (type == ICMP_PARAMETERPROB)
178 {
179 sk->err = EPROTO;
180 sk->error_report(sk);
181 return;
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196 if (code < 13 && icmp_err_convert[code].fatal)
197 {
198 sk->err = icmp_err_convert[code].errno;
199 sk->error_report(sk);
200 }
201 }
202
203
204 static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr, unsigned long base)
205 {
206 return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
207 }
208
209 struct udpfakehdr
210 {
211 struct udphdr uh;
212 int daddr;
213 int other;
214 const char *from;
215 int wcheck;
216 };
217
218
219
220
221
222
223
224 static void udp_getfrag(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen)
225 {
226 struct udpfakehdr *ufh = (struct udpfakehdr *)p;
227 const char *src;
228 char *dst;
229 unsigned int len;
230
231 if (offset)
232 {
233 len = fraglen;
234 src = ufh->from+(offset-sizeof(struct udphdr));
235 dst = to;
236 }
237 else
238 {
239 len = fraglen-sizeof(struct udphdr);
240 src = ufh->from;
241 dst = to+sizeof(struct udphdr);
242 }
243 ufh->wcheck = csum_partial_copy_fromuser(src, dst, len, ufh->wcheck);
244 if (offset == 0)
245 {
246 ufh->wcheck = csum_partial((char *)ufh, sizeof(struct udphdr),
247 ufh->wcheck);
248 ufh->uh.check = csum_tcpudp_magic(saddr, ufh->daddr,
249 ntohs(ufh->uh.len),
250 IPPROTO_UDP, ufh->wcheck);
251 if (ufh->uh.check == 0)
252 ufh->uh.check = -1;
253 memcpy(to, ufh, sizeof(struct udphdr));
254 }
255 }
256
257
258
259
260
261
262
263
264 static void udp_getfrag_nosum(const void *p, __u32 saddr, char * to, unsigned int offset, unsigned int fraglen)
265 {
266 struct udpfakehdr *ufh = (struct udpfakehdr *)p;
267 const char *src;
268 char *dst;
269 unsigned int len;
270
271 if (offset)
272 {
273 len = fraglen;
274 src = ufh->from+(offset-sizeof(struct udphdr));
275 dst = to;
276 }
277 else
278 {
279 len = fraglen-sizeof(struct udphdr);
280 src = ufh->from;
281 dst = to+sizeof(struct udphdr);
282 }
283 memcpy_fromfs(dst,src,len);
284 if (offset == 0)
285 memcpy(to, ufh, sizeof(struct udphdr));
286 }
287
288
289
290
291
292
293 static int udp_send(struct sock *sk, struct sockaddr_in *sin,
294 const unsigned char *from, int len, int rt,
295 __u32 saddr)
296 {
297 int ulen = len + sizeof(struct udphdr);
298 int a;
299 struct udpfakehdr ufh;
300
301 if(ulen>65535-sizeof(struct iphdr))
302 return -EMSGSIZE;
303
304 ufh.uh.source = sk->dummy_th.source;
305 ufh.uh.dest = sin->sin_port;
306 ufh.uh.len = htons(ulen);
307 ufh.uh.check = 0;
308 ufh.daddr = sin->sin_addr.s_addr;
309 ufh.other = (htons(ulen) << 16) + IPPROTO_UDP*256;
310 ufh.from = from;
311 ufh.wcheck = 0;
312
313
314
315
316
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);
326 else
327 a = ip_build_xmit(sk, udp_getfrag, &ufh, ulen,
328 sin->sin_addr.s_addr, saddr, sk->opt, rt, IPPROTO_UDP);
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 sk->inuse = 1;
394
395
396 tmp = udp_send(sk, usin, from, len, flags, saddr);
397
398
399 release_sock(sk);
400 return(tmp);
401 }
402
403
404
405
406
407 static int udp_write(struct sock *sk, const unsigned char *buff, int len, int noblock,
408 unsigned flags)
409 {
410 return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
411 }
412
413
414
415
416
417
418 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
419 {
420 int err;
421 switch(cmd)
422 {
423 case TIOCOUTQ:
424 {
425 unsigned long amount;
426
427 if (sk->state == TCP_LISTEN) return(-EINVAL);
428 amount = sock_wspace(sk);
429 err=verify_area(VERIFY_WRITE,(void *)arg,
430 sizeof(unsigned long));
431 if(err)
432 return(err);
433 put_fs_long(amount,(unsigned long *)arg);
434 return(0);
435 }
436
437 case TIOCINQ:
438 {
439 struct sk_buff *skb;
440 unsigned long amount;
441
442 if (sk->state == TCP_LISTEN) return(-EINVAL);
443 amount = 0;
444 skb = skb_peek(&sk->receive_queue);
445 if (skb != NULL) {
446
447
448
449
450
451 amount = skb->len;
452 }
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 default:
462 return(-EINVAL);
463 }
464 return(0);
465 }
466
467
468
469
470
471
472
473 int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
474 int noblock, int flags,int *addr_len)
475 {
476 int copied = 0;
477 int truesize;
478 struct sk_buff *skb;
479 int er;
480 struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
481
482
483
484
485
486 if (addr_len)
487 *addr_len=sizeof(*sin);
488
489
490
491
492
493
494 skb=skb_recv_datagram(sk,flags,noblock,&er);
495 if(skb==NULL)
496 return er;
497
498 truesize = skb->len - sizeof(struct udphdr);
499 copied = min(len, truesize);
500
501
502
503
504
505 skb_copy_datagram_iovec(skb,sizeof(struct udphdr),msg->msg_iov,copied);
506 sk->stamp=skb->stamp;
507
508
509 if (sin)
510 {
511 sin->sin_family = AF_INET;
512 sin->sin_port = skb->h.uh->source;
513 sin->sin_addr.s_addr = skb->daddr;
514 }
515
516 skb_free_datagram(skb);
517 release_sock(sk);
518 return(copied);
519 }
520
521 int udp_recvfrom(struct sock *sk, unsigned char *ubuf, int size, int noblock, unsigned flags,
522 struct sockaddr_in *sa, int *addr_len)
523 {
524 struct iovec iov;
525 struct msghdr msg;
526
527 iov.iov_base = ubuf;
528 iov.iov_len = size;
529
530 msg.msg_name = (void *)sa;
531 msg.msg_namelen = 0;
532 if (addr_len)
533 msg.msg_namelen = *addr_len;
534 msg.msg_accrights = NULL;
535 msg.msg_iov = &iov;
536 msg.msg_iovlen = 1;
537
538 return udp_recvmsg(sk, &msg, size, noblock, flags, addr_len);
539 }
540
541
542
543
544
545
546 int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
547 unsigned flags)
548 {
549 return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
550 }
551
552
553 int udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
554 {
555 struct rtable *rt;
556 __u32 sa;
557 if (addr_len < sizeof(*usin))
558 return(-EINVAL);
559
560 if (usin->sin_family && usin->sin_family != AF_INET)
561 return(-EAFNOSUPPORT);
562 if (usin->sin_addr.s_addr==INADDR_ANY)
563 usin->sin_addr.s_addr=ip_my_addr();
564
565 if(!sk->broadcast && ip_chk_addr(usin->sin_addr.s_addr)==IS_BROADCAST)
566 return -EACCES;
567
568 rt=(sk->localroute?ip_rt_local:ip_rt_route)((__u32)usin->sin_addr.s_addr, NULL, &sa);
569 if(rt==NULL)
570 return -ENETUNREACH;
571 sk->saddr = sa;
572 sk->daddr = usin->sin_addr.s_addr;
573 sk->dummy_th.dest = usin->sin_port;
574 sk->state = TCP_ESTABLISHED;
575 udp_cache_zap();
576 sk->ip_route_cache = rt;
577 sk->ip_route_stamp = rt_stamp;
578 return(0);
579 }
580
581
582 static void udp_close(struct sock *sk, int timeout)
583 {
584 sk->inuse = 1;
585 sk->state = TCP_CLOSE;
586 if(uh_cache_sk==sk)
587 udp_cache_zap();
588 if (sk->dead)
589 destroy_sock(sk);
590 else
591 release_sock(sk);
592 }
593
594
595
596
597
598
599 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
600 __u32 daddr, unsigned short len,
601 __u32 saddr, int redo, struct inet_protocol *protocol)
602 {
603 struct sock *sk;
604 struct udphdr *uh;
605 unsigned short ulen;
606 int addr_type = IS_MYADDR;
607
608 if(!dev || dev->pa_addr!=daddr)
609 addr_type=ip_chk_addr(daddr);
610
611
612
613
614
615 uh = (struct udphdr *) skb->h.uh;
616
617 ip_statistics.IpInDelivers++;
618
619
620
621
622
623 ulen = ntohs(uh->len);
624
625 if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh))
626 {
627 NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len));
628 udp_statistics.UdpInErrors++;
629 kfree_skb(skb, FREE_WRITE);
630 return(0);
631 }
632
633
634
635
636
637
638
639
640 if (uh->check && (
641 ( skb->ip_summed && udp_check(uh, len, saddr, daddr, skb->csum ) ) ||
642 ( !skb->ip_summed && udp_check(uh, len, saddr, daddr,csum_partial((char*)uh, len, 0)))
643 )
644 )
645 {
646
647
648
649
650
651
652 NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
653 ntohl(saddr),ntohs(uh->source),
654 ntohl(daddr),ntohs(uh->dest),
655 ulen));
656 udp_statistics.UdpInErrors++;
657 kfree_skb(skb, FREE_WRITE);
658 return(0);
659 }
660
661
662 len=ulen;
663
664 #ifdef CONFIG_IP_MULTICAST
665 if (addr_type!=IS_MYADDR)
666 {
667
668
669
670 struct sock *sknext=NULL;
671 sk=get_sock_mcast(udp_prot.sock_array[ntohs(uh->dest)&(SOCK_ARRAY_SIZE-1)], uh->dest,
672 saddr, uh->source, daddr);
673 if(sk)
674 {
675 do
676 {
677 struct sk_buff *skb1;
678
679 sknext=get_sock_mcast(sk->next, uh->dest, saddr, uh->source, daddr);
680 if(sknext)
681 skb1=skb_clone(skb,GFP_ATOMIC);
682 else
683 skb1=skb;
684 if(skb1)
685 udp_deliver(sk, uh, skb1, dev,saddr,daddr,len);
686 sk=sknext;
687 }
688 while(sknext!=NULL);
689 }
690 else
691 kfree_skb(skb, FREE_READ);
692 return 0;
693 }
694 #endif
695 if(saddr==uh_cache_saddr && daddr==uh_cache_daddr && uh->dest==uh_cache_dport && uh->source==uh_cache_sport)
696 sk=(struct sock *)uh_cache_sk;
697 else
698 {
699 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
700 uh_cache_saddr=saddr;
701 uh_cache_daddr=daddr;
702 uh_cache_dport=uh->dest;
703 uh_cache_sport=uh->source;
704 uh_cache_sk=sk;
705 }
706
707 if (sk == NULL)
708 {
709 udp_statistics.UdpNoPorts++;
710 if (addr_type == IS_MYADDR)
711 {
712 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
713 }
714
715
716
717
718 skb->sk = NULL;
719 kfree_skb(skb, FREE_WRITE);
720 return(0);
721 }
722 return udp_deliver(sk,uh,skb,dev, saddr, daddr, len);
723 }
724
725 static int udp_deliver(struct sock *sk, struct udphdr *uh, struct sk_buff *skb, struct device *dev, long saddr, long daddr, int len)
726 {
727 skb->sk = sk;
728 skb->dev = dev;
729 skb_trim(skb,len);
730
731
732
733
734
735 skb->daddr = saddr;
736 skb->saddr = daddr;
737
738
739
740
741
742
743
744
745
746 if (sock_queue_rcv_skb(sk,skb)<0)
747 {
748 udp_statistics.UdpInErrors++;
749 ip_statistics.IpInDiscards++;
750 ip_statistics.IpInDelivers--;
751 skb->sk = NULL;
752 kfree_skb(skb, FREE_WRITE);
753 release_sock(sk);
754 return(0);
755 }
756 udp_statistics.UdpInDatagrams++;
757 release_sock(sk);
758 return(0);
759 }
760
761
762 struct proto udp_prot = {
763 udp_close,
764 udp_read,
765 udp_write,
766 udp_sendto,
767 udp_recvfrom,
768 ip_build_header,
769 udp_connect,
770 NULL,
771 ip_queue_xmit,
772 NULL,
773 NULL,
774 NULL,
775 udp_rcv,
776 datagram_select,
777 udp_ioctl,
778 NULL,
779 NULL,
780 ip_setsockopt,
781 ip_getsockopt,
782 NULL,
783 udp_recvmsg,
784 128,
785 0,
786 "UDP",
787 0, 0,
788 {NULL,}
789 };