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