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